目录

一、本章重点

二、带头双向循环链表介绍

2.1什么是带头双向循环链表?

2.2最常用的两种链表结构

三、带头双向循环链表常用接口实现

3.1结构体创建

四、实现接口总结

五、在线oj训练与详解


一、本章重点

  1. 带头双向循环链表介绍
  2. 带头双向循环链表常用接口实现
  3. 实现接口总结
  4. 在线oj训练与详解

二、带头双向循环链表介绍

2.1什么是带头双向循环链表?

  • 带头:存在一个哨兵位的头节点,该节点是个无效节点,不存储任何有效信息,但使用它可以方便我们头尾插和头尾删时不用判断头节点指向NULL的情况,同时也不需要改变头指针的指向,也就不需要传二级指针了。
  • 双向:每个结构体有两个指针,分别指向前一个结构体和后一个结构体。
  • 循环:最后一个结构体的指针不再指向NULL,而是指向第一个结构体。(单向)
  • 第一个结构体的前指针指向最后一个结构体,最后一个结构体的后指针指向第一个结构体(双向)。

图解

 2.2最常用的两种链表结构

  • 更具有无头,单双向,是否循环组合起来有8种结构,但最长用的还是无头单向非循环链表和带头双向循环链表
  • 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。另外这种结构在笔试面试中出现很多。
  •  带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。

三、带头双向循环链表常用接口实现 

3.1结构体创建

typedef int DataType;
typedef struct DListNode
{DataType data;DListNode* prev;DListNode* next;
}DListNode;

3.2带头双向循环链表的初始化 

void DListInint(DListNode** pphead)
{*pphead = (DListNode*)malloc(sizeof(DListNode));(*pphead)->next = (*pphead);(*pphead)->prev = (*pphead);
}

 或者使用返回节点的方法也能实现初始化

DListNode* DListInit(){DListNode* phead = (DListNode*)malloc(sizeof(DListNode));phead->next = phead;phead->prev = phead;return phead;}

 3.3创建新节点

DListNode* BuyDListNode(DataType x)
{DListNode* temp = (DListNode*)malloc(sizeof(DListNode));if (temp == NULL){printf("malloc fail\n");exit(-1);}temp->prev = NULL;temp->next = NULL;temp->data = x;return temp;
}

 3.4尾插

void DListPushBack(DListNode* phead,DataType x)
{DListNode* newnode = BuyDListNode(x);DListNode* tail = phead->prev;tail->next = newnode;newnode->prev = tail;newnode->next = phead;phead->prev = newnode;
}

 3.5打印链表

void DListNodePrint(DListNode* phead)
{DListNode* cur = phead->next;while (cur != phead){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}

 3.6头插

void DListNodePushFront(DListNode* phead, DataType x)
{DListNode* next = phead->next;DListNode* newnode = BuyDListNode(x);next->prev = newnode;newnode->next = next;newnode->prev = phead;phead->next = newnode;
}

 3.7尾删

void DListNodePopBack(DListNode* phead)
{if (phead->next == phead){return;}DListNode* tail = phead->prev;DListNode* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;
}

 3.8头删

void DListNodePopFront(DListNode* phead)
{if (phead->next == phead){return;}DListNode* firstnode = phead->next;DListNode* secondnode = firstnode->next;secondnode->prev = phead;phead->next = secondnode;free(firstnode);firstnode = NULL;
}

 3.9查找data(返回data的节点地址)

DListNode* DListNodeFind(DListNode* phead, DataType x)
{DListNode* firstnode = phead->next;while (firstnode != phead){if (firstnode->data == x){return firstnode;}firstnode = firstnode->next;}return NULL;
}

   3.10在pos位置之前插入节点

void DListNodeInsert(DListNode* pos, DataType x)
{DListNode* prev = pos->prev;DListNode* newnode = BuyDListNode(x);newnode->next = pos;newnode->prev = prev;prev->next = newnode;pos->prev = newnode;
}

3.11删除pos位置的节点

void DListNodeErase(DListNode* pos)
{DListNode* prev = pos->prev;DListNode* next = pos->next;prev->next = next;next->prev = prev;free(pos);pos = NULL;
}

四、实现接口总结

  1. 多画图能给清晰展示变化的过程,有利于实现编程。
  2. 小知识head->next既可表示前一个结构体的成员变量,有可表示后一个结构体的地址。当head->next作为左值时代表的是成员变量,作右值时代表的是后一个结构体的地址。对于链表来说理解这一点非常重要。
  3. 实践实践出真知
  4. 带头双向循环链表相比于单链表,它实现起来更简单,不用向单链表一样分情况讨论链表的长度。虽然结构较复杂,但使用起来更简单,更方便。

 五、在线oj训练与详解

5.1链表的中间节点(力扣)

给定一个头结点为 head 的非空单链表,返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

输入:[1,2,3,4,5]
输出:此列表中的结点 3 (序列化形式:[3,4,5])
返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。
注意,我们返回了一个 ListNode 类型的对象 ans,这样:
ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.

来源:力扣(LeetCode)

 思路:快慢指针

取两个指针,初始时均指向head,一个为快指针(fast)一次走两步,另一个为慢指针(slow)一次走一步,当快指针满足fast==NULL(偶数个节点)或者fast->next==NULL(奇数个节点)时,slow指向中间节点,返回slow即可。

struct ListNode* middleNode(struct ListNode* head)
{struct ListNode* fast=head;struct ListNode* slow=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;}return slow;
}

线性表之带头双向循环链表相关推荐

  1. 比特数据结构与算法(第二章收尾)带头双向循环链表的实现

    1.链表的分类 链表的分类 ① 单向或者双向 ② 带头或者不带头 ③ 循环或者非循环 常用的链表: 根据上面的分类我们可以细分出8种不同类型的链表,这么多链表我们一个个讲解这并没有意义.我们实际中最常 ...

  2. 【数据结构】-关于带头双向循环链表的增删查改

    作者:低调 作者宣言:写好每一篇博客 文章目录 前言 一.带头双向循环链表的实现 1.1创建返回链表的头结点 1.2开辟一个新的结点 1.3双向链表的销毁 1.4双向链表的打印 1.5双向链表尾插 1 ...

  3. 一文搞定带头双向循环链表

    什么是链表 链表的种类 最经典的两种链表 带头双向循环链表详细 什么是链表 在数据结构线性表里 除了顺序表 还有一种我们不得不说 他就是链表 链表的关键就是指针 创建出一块节点空间存储着 一边是val ...

  4. 数据结构与算法 | 带头双向循环链表

    上一节里实现的是最简单的链表,在实际中那种链表不会单独用来存储数据,更多是作为其他数据结构的子结构,如图的邻接表等.而比较常用的就是带头双向循环链表. 通过对比我们可以看出有三个不同,多了头节点,链表 ...

  5. 【数据结构】链表:带头双向循环链表的增删查改

    本篇要分享的内容是带头双向链表,以下为本片目录 目录 一.链表的所有结构 二.带头双向链表 2.1尾部插入 2.2哨兵位的初始化 2.3头部插入 2.4 打印链表 2.5尾部删除 2.6头部删除 2. ...

  6. 数据结构-带头双向循环链表(增删查改详解)

    在上一篇博客中,详细介绍了单链表的增删查改,虽然单链表的结构简单,但是用起来却不是那么顺手.因此根据单链表的种种缺点,这篇博客所介绍的带头双向循环链表将会带来极大的优化. 上图就是带头双向循环链表的主 ...

  7. 【数据结构】带头双向循环链表

    各位读者们好久不见了,咋们接着上一期链表来,今天来实现一下链表最难的结构,同时也是实现起来最简单的结构--带头双向循环链表.话不多说,进入主题 文章目录 前言 实现带头双向循环链表 DList.h头文 ...

  8. 【数据结构初阶】链表(下)——带头双向循环链表的实现

    目录 带头双向循环链表的实现 1.带头双向循环链表的节点类型 2.创建带头双向循环链表的节点 3.向带头双向循环链表中插入数据 <3.1>从链表尾部插入数据 <3.2>从链表头 ...

  9. 实现简单的带头双向循环链表

    双向链表 1. 带头双向循环链表的定义 2. 带头双向循环链表的创建 3. 带头双向循环链表的增删改查 (1)头插头删 (2)尾插尾删 (3)pos位置的前插与删除 4.插入与删除改良 1. 带头双向 ...

  10. c语言实现数据结构中的带头双向循环链表

    目录标题 一.单向链表的不足 二.带头双向链表的准备 三.带头双向链表的初始化 四.带头双向链表的尾插 五.带头双向链表的打印 六.带头双向链表头插 七.判断链表是否为空 八.带头双向链表尾删 九.带 ...

最新文章

  1. 预告 · Flutter Live 2018 全球同步直播
  2. XCOM串口助手打印不出数据
  3. 基于MATLAB的语音信号的时域特性分析(一)——分帧、窗函数
  4. aws python lambda_AWS Lambda
  5. red hat 5 和 oracle
  6. SpringOne Platform 2016回顾
  7. 上传文件Base64格式(React)
  8. python api测试框架_python api 测试框架
  9. django 1.8 官方文档翻译: 14-4-1 重定向应用
  10. radvd移植到arm交叉编译问题解决
  11. VB6的后期绑定和前期绑定
  12. [转载] python enumerate函数 实例_python中使用enumerate函数遍历元素实例
  13. 知乎:学习分布式系统需要怎样的知识?
  14. matpower安装问题
  15. 无线通信设备安装工程概预算编制_起重设备安装资质承接多大工程
  16. 【工具】——远程协助(向日葵)
  17. 如何删除ie浏览器缓存文件、缓存js
  18. java-数组-数组缩减
  19. 媒体专访 | 许彬教授:我们离元宇宙Big Bang有多近?
  20. 【NLP】文本分类算法-基于字符级的无词嵌入双向循环神经网络(双向 GRU)

热门文章

  1. 图片飞出去的特效怎么做?3分钟AE制作教程
  2. 红巨星粒子Red Giant Trapcode Suite
  3. 【2020】微软 MCSA,MCSD,MCSE认证于2021年1月31停用,此后您将无法再获得此认证 - GJYJSJGS - 高级云计算架构师
  4. jquery版本问题
  5. DIY 3D打印机测试
  6. 微信Emoji工具-EmojiUtil
  7. matlab牛顿插值法
  8. Linux部署django项目最全,linux部署django项目流程(全)
  9. 360手机助手电脑版 v2.4.0.1251 官方版
  10. m3u8 ts文件利用系统工具COPY合并序列TS文件