数据结构 —— 双向链表(超详细图解 & 接口函数实现)

这篇具有很好参考价值的文章主要介绍了数据结构 —— 双向链表(超详细图解 & 接口函数实现)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

系列文章目录

数据结构 —— 顺序表
数据结构 —— 单链表
数据结构 —— 双向链表
数据结构 —— 队列
数据结构 —— 栈
数据结构 —— 堆
数据结构 —— 二叉树
数据结构 —— 八大排序



前言

数据结构是计算机存储、组织数据的方式。数据结构是指相互之间存在一种或多种特定关系的数据元素的集合。数据结构是一种十分优秀的解决实际问题的模板,是先进思想的结晶。博主将会用代码结合大量图解,对数据结构进行深度剖析,以便大家更好的学习数据结构的思想。


一、示例问题:城市对外回环交通

城市对外交通实现了从一个城市到另一个城市的道路,但今天所讨论的仅限于一个城市连接其他两个城市的回环交通结构。

1.城市回环交通

城市对外交通指的是城市与城市之间的交通,是连接城市与城市之间往返的重要路径

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

2.逻辑示意图

城市回环交通结构与本文将的内容极其相似,我们由城市的回环交通来引入双向带头循环链表

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

3.双向链表的引入

双向链表的引入:既能指向前一个节点又指向下一个节点存储内容地址

二、双向链表的概念

1.定义

链表:由 n 个节点链接成一个链表,即线性表的链式存储结构

双向链表:双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱

节点:

  1. 我们把存储数据元素信息的域称为数据域。
  2. 存储数据元素之间的链接信息即下一个存储数据元素地址的部分称为指针域。
  3. 由数据域和指针域组成的数据元素a的存储映像称为节点。

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

2.结构

双向链表的结构类型

typedef int LTDateType;			//便于更改存储类型

typedef struct ListNode {		
    LTDateType data;			//数据域:存储数据元素信息
    struct ListNode *prev;		//指针域:存储上一个节点信息
    struct ListNode *next;		//指针域:存储下一个节点信息
} ListNode;

3.存储

存储:用动态开辟的sizeof(ListNode)大小的一块空间进行存储

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

三、双向链表的接口函数

1.动态申请空间

动态开辟一块sizeof(ListNode)大小的空间进行存储

// 动态申请一个结点
ListNode *BuyListNode(LTDateType x) {
    ListNode *node = (ListNode *) malloc(sizeof(ListNode));
    node->data = x;
    node->prev = NULL;
    node->next = NULL;
    return node;
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

2.创建哨兵位

创建返回链表的哨兵位

// 创建返回链表的哨兵位
ListNode *ListInit() {
    ListNode *pHead = BuyListNode(-1);
    pHead->prev = pHead;
    pHead->next = pHead;
    return pHead;
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

3.查找指定数据

双向链表查找指定数据

// 双向链表查找
ListNode *ListFind(ListNode *pHead, LTDateType x) {
    assert(pHead);

    ListNode *curr = pHead->next;
    while (curr != pHead) {
        if (curr->data == x) {
            return curr;
        }
        curr = curr->next;
    }
    return NULL;
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

4.指定位置插入

双向链表在指定位置 pos 插入 x

// 双向链表在pos位置插入x
void ListInsert(ListNode *pos, LTDateType x) {
    assert(pos);

    ListNode *newNode = BuyListNode(x);
    ListNode *prev = pos->prev;

    newNode->prev = prev;
    newNode->next = pos;
    prev->next = newNode;
    pos->prev = newNode;
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

5.指定位置删除

双向链表删除在指定位置 pos

// 双向链表在pos位置删除
void ListErase(ListNode *pos) {
    assert(pos);
    assert(pos != pos->next);

    pos->next->prev = pos->prev;
    pos->prev->next = pos->next;
    free(pos);
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

6.头部插入

双向链表在哨兵位之后的位置插入 x

// 双向链表头插
void ListPushFront(ListNode *pHead, LTDateType x) {
    ListInsert(pHead->next, x);
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

7.头部删除

双向链表删除哨兵位的后一个节点

// 双向链表头删
void ListPopFront(ListNode *pHead) {
    ListErase(pHead->next);
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

8.尾部插入

双向链表在哨兵位之前的位置插入 x

// 双向链表尾插
void ListPushBack(ListNode *pHead, LTDateType x) {
    ListInsert(pHead, x);
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

9.尾部删除

双向链表删除哨兵位的前一个节点

// 双向链表尾删
void ListPopBack(ListNode *pHead) {
    ListErase(pHead->prev);
}

数据结构 —— 双向链表(超详细图解 & 接口函数实现)

10.计算链表大小

计算双向链表的大小

// 计算大小
int ListSize(ListNode *pHead) {
    ListNode *curr = pHead->next;
    int size = 0;
    while (curr != pHead) {
        size++;
        curr = curr->next;
    }
    return size;
}

11.销毁链表

销毁双向链表,请手动置空

// 销毁(手动置空)
void ListDestory(ListNode *pHead) {
    ListNode *curr = pHead->next;
    while (curr != pHead) {
        ListNode *next = curr->next;
        free(curr);
        curr = next;
    }
    free(pHead);
}

四、总结

双向链表是解决实际问题时极其常用的一种数据结构,是非常重要的解决问题的方式。双向链表的各种接口的复现,有利于更好的学习数据结构的思想,有利于开阔视野,学习前辈的智慧结晶。对我们后续解决实际问题也会有很大帮助。文章来源地址https://www.toymoban.com/news/detail-502211.html

到了这里,关于数据结构 —— 双向链表(超详细图解 & 接口函数实现)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【数据结构与算法】 - 双向链表 - 详细实现思路及代码

    前几篇文章介绍了怎样去实现单链表、单循环链表, 这篇文章主要介绍 双向链表 以及实现双向链表的步骤,最后提供我自己根据理解实现双向链表的C语言代码 。跟着后面实现思路看下去,应该可以看懂代码,看懂代码后,就对双向链表有了比较抽象的理解了,最后自己再

    2024年02月01日
    浏览(28)
  • 【数据结构】双向链表 超详细 (含:何时用一级指针或二级指针;指针域的指针是否要释放)

    目录 一、简介 二. 双链表的实现 1.准备工作及其注意事项 1.1 先创建三个文件 1.2 注意事项:帮助高效记忆 1.3   关于什么时候 用 一级指针接收,什么时候用 二级指针接收? 1.4 释放节点时,要将节点地址 置为NULL,难道 节点内部的 指针域的指针 就不用置为 NULL吗?  2.双链

    2024年02月20日
    浏览(73)
  • 数据结构-链表结构-双向链表

    双向链表也叫双链表,与单向链表不同的是,每一个节点有三个区域组成:两个指针域,一个数据域 前一个指针域:存储前驱节点的内存地址 后一个指针域:存储后继节点的内存地址 数据域:存储节点数据 以下就是双向链表的最基本单位 节点的前指针域指向前驱,后指针

    2024年02月04日
    浏览(36)
  • 数据结构:手撕图解双向循环链表

    在前面学完单链表后,我们思考这样一个问题,单链表和顺序表比起来,功能确实相当强大,有很多优势,但是于此同时,我们也应思考下面的问题 单链表有什么不足的地方? 如果你把单链表的各个函数都自己实现过,那么下面的问题你一定有相同的感悟 单链表实现尾插尾

    2024年02月15日
    浏览(76)
  • 数据结构---手撕图解双向循环链表

    在前面学完单链表后,我们思考这样一个问题,单链表和顺序表比起来,功能确实相当强大,有很多优势,但是于此同时,我们也应思考下面的问题 单链表有什么不足的地方? 如果你把单链表的各个函数都自己实现过,那么下面的问题你一定有相同的感悟 单链表实现尾插尾

    2024年02月15日
    浏览(43)
  • 【数据结构】双向奔赴的爱恋 --- 双向链表

    关注小庄 顿顿解馋๑ᵒᯅᵒ๑ 引言:上回我们讲解了单链表(单向不循环不带头链表),我们可以发现他是存在一定缺陷的,比如尾删的时候需要遍历一遍链表,这会大大降低我们的性能,再比如对于链表中的一个结点我们是无法直接访问它的上一个结点,那有什么解决方法呢

    2024年04月08日
    浏览(84)
  • 数据结构——双向链表

    🍇系列专栏:🌙数据结构 🍉  欢迎关注:👍点赞🍃收藏🔥留言 🍎 博客主页:🌙_麦麦_的博客_CSDN博客-领域博主 🌙如果我们都不能够拥有黑夜,又该怎样去仰望星空?   目录 一、前言 二、正文——双向链表的实现 2.1模块化 2.2 数据类型与结构体定义  2.3链表的初始化

    2024年02月02日
    浏览(35)
  • 数据结构-双向链表

    在单链表那一篇博客中介绍了单链表和双向链表的优缺点,所以此篇博客直接分享怎样实现一个带头双向循环链表。 单链表博客: 首先我们需要写一个结构体,双向带头链表的话需要一个前驱指针prev和一个后驱指针next,前驱指针的作用是方便找尾节点,因为头节点的prev指

    2024年02月05日
    浏览(34)
  • 数据结构双向链表

    Hello,好久不见,今天我们讲链表的双向链表,这是一个很厉害的链表,带头双向且循环,学了这个链表,你会发现顺序表的头插头删不再是一个麻烦问题,单链表的尾插尾删也变得简单起来了,那废话不多说,让我们开始我们的学习吧! 首先我们要了解它的物理和逻辑结构

    2024年02月11日
    浏览(32)
  • 数据结构 - 双向链表

    文章目录 目录 文章目录 前言 一、什么是双向链表? 双向链表有什么优势? 二、双向链表的设计和实现 1.设计思想 尾增 : 在链表的末尾添加新的元素  头插 : 在链表头部插入节点  删除 : 根据val的值删除节点  查找 : 根据索引的值查找并返回节点 总结 大家好,今天给大家讲解

    2024年02月09日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包