目录

序言

带头双向循环链表

1. 概念

2. 效果展示图

3. 接口实现

3.01. 本文章要实现的接口

​3.02. 双链表的实现

3.03. 双链表的初始化

3.04. 打印链表

3.05. 动态申请一个节点

3.06. 头插

3.07. 尾插

3.08. 头删

3.09. 尾删

3.10. 查某个值,返回地址

3.11. 某个位置前插入数据

3.12. 删除某个位置数据

3.13. 改某个值

3.14. 销毁

总结

4. 源代码

test.c

List.h

List.c


谁都不能阻挡你成为更优秀的人。

序言

首先本文是和上一篇单链表有关联哈,上篇文章已经详细说明了链表的概念和分类,这里就不过多赘述了,就简单说明一下哈,链接在下面。一篇解单链表(0基础看)(C语言)《数据结构与算法》_原来45的博客-CSDN博客

上文我们讲到了链表最重要的两个分类,一个是单向不带头不循环,本篇文章就讲另一个重要的带头双向循环链表哈,废话不多说,直接看代码。

对了,这里附上作者的qq:2777137742。要是有什么问题可以在qq上面问我哈,或者文章有错误的地方,期待和大家共同讨论,因为csdn的消息有可能会遗漏哈,最后感谢你的支持。

带头双向循环链表

1. 概念

带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都
是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带
来很多优势,实现反而简单了,后面我们代码实现了就知道了。
 

这里我们来慢慢揭晓上文说到的实现更简单,以及单链表的缺点。缺点就直接说了,我们可以很直观得发现单链表的两个很大的缺点,一个是尾插尾删等都是需要遍历也就是说时间复杂度是O(N),但是双链表对应的都是O(1),效率之高。另一个缺点就是单链表不能找到自己的上一个节点,这都是很大的缺陷。然后我们接着看双链表实现的优势。

2. 效果展示图

3. 接口实现

还是老话,对于接口的实现我们首先是要知道要实现什么,本文是对于双链表的基本使用,所以就只实现顺序表的增删查改,还有特定位置前插入删除特定位置值等当然代码也不一定要作者这么写,这里只是提供一种思路,废话不多说,看代码。

3.01. 本文章要实现的接口

3.02. 双链表的实现

这是命名是ListNode是与c++对应的,大家也可以和单链表SListNode对应取名DListnode,但是作者为了养成一个好的习惯就取名为了ListNode哈。

3.03. 双链表的初始化

注意这里初始化是自己指向自己,因为是循环,然后本篇文章不用二级指针(不用传地址),这里就用了一个返回值。

3.04. 打印链表

3.05. 动态申请一个节点

3.06. 头插

3.07. 尾插

3.08. 头删

3.09. 尾删

3.10. 查某个值,返回地址

3.11. 某个位置前插入数据

3.12. 删除某个位置数据

3.13. 改某个值

3.14. 销毁

总结

我们可以发现对于带头双向循环链表的实现不需要像单链表那样要去判断没有或者有一个节点的情况,结构非常之完美,可以利用头结点进行各种变化,实现也非常简单,而且也不用传地址。

这里要再解释一下为什么可以不传地址,因为我们的头没有改变,不需要改变头,这个改变指的是我们一开始传的参数plist,他是一直指向我们的头的,是指向没有变,内容可以改变,也就是说plist的前驱prev后继next的指向和date可以变的,这个理解很重要!

4. 源代码

test.c

#include"List.h"int main()
{printf("初始化\n");ListNode* plist = ListInit();printf("头插 1 2 3 并打印\n");ListPushFront(plist, 1);ListPushFront(plist, 2);ListPushFront(plist, 3);ListPrint(plist);printf("尾插4 5 6 并打印\n");ListPushBack(plist, 4);ListPushBack(plist, 5);ListPushBack(plist, 6);ListPrint(plist);printf("头删并打印\n");ListPopFront(plist);ListPrint(plist);printf("尾删并打印\n");ListPopBack(plist);ListPrint(plist);printf("1前插入3并打印\n");ListNode* pos = ListFind(plist, 1);ListInsert(plist, pos, 3);ListPrint(plist);printf("2前插入8并打印\n");pos = ListFind(plist, 2);ListInsert(plist, pos, 8);ListPrint(plist);printf("删除4并打印\n");pos = ListFind(plist, 4);ListErase(plist, pos);ListPrint(plist);printf("把1改成9并打印\n");ListChange(plist, 1, 9);ListPrint(plist);printf("销毁链表\n");ListDestory(plist);return 0;
}

List.h

#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>
#include<malloc.h>
#include<assert.h>typedef int ListDateType;typedef struct ListNode
{struct ListNode* prev;struct ListNode* next;ListDateType date;
}ListNode;//增删查改//初始化
ListNode* ListInit();
//销毁
void ListDestory(ListNode* phead);
//得到一个节点
ListNode* BuyListNode(ListDateType x);
//打印
void ListPrint(ListNode* phead);//头插
void ListPushFront(ListNode* phead, ListDateType x);
//尾插
void ListPushBack(ListNode* phead, ListDateType x);
//头删
void ListPopFront(ListNode* phead);
//尾删
void ListPopBack(ListNode* phead);//查某个值,返回地址
ListNode* ListFind(ListNode* phead, ListDateType x);
//改某个值
void ListChange(ListNode* phead, ListDateType source, ListDateType destination);//某个位置前插入数据
void ListInsert(ListNode* phead, ListNode* pos, ListDateType x);
//删除某个位置数据
void ListErase(ListNode* phead, ListNode* pos);

List.c

#include"List.h"//初始化
ListNode* ListInit()
{ListNode* phead = BuyListNode(0);phead->prev = phead;phead->next = phead;phead->date = 0;return phead;
}//得到一个节点
ListNode* BuyListNode(ListDateType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));newnode->prev = NULL;newnode->next = NULL;newnode->date = x;return newnode;
}//头插
void ListPushFront(ListNode* phead, ListDateType x)
{assert(phead);ListNode* newnode = BuyListNode(x);ListNode* first = phead->next;phead->next = newnode;newnode->prev = phead;newnode->next = first;first->prev = newnode;
}//尾插
void ListPushBack(ListNode* phead, ListDateType x)
{assert(phead);ListNode* tail = phead->prev;ListNode* newnode = BuyListNode(x);phead->prev = newnode;newnode->next=phead;tail->next = newnode;newnode->prev = tail;
}//打印
void ListPrint(ListNode* phead)
{ListNode* cur = phead->next;while (cur != phead){printf("%d ", cur->date);cur = cur->next;}printf("\n");
}//头删
void ListPopFront(ListNode* phead)
{assert(phead);//别把头删了assert(phead->next != phead);ListNode* first = phead->next;phead->next = first->next;first->next->prev = phead;free(first);first = NULL;
}//尾删
void ListPopBack(ListNode* phead)
{assert(phead);//别把头删了assert(phead->next != phead);ListNode* tail = phead->prev;ListNode* prev = tail->prev;prev->next = phead;phead->prev = prev;free(tail);tail = NULL;
}//查某个值,返回地址
ListNode* ListFind(ListNode* phead, ListDateType x)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){if (cur->date == x){return cur;}else{cur = cur->next;}}return NULL;
}//某个位置前插入数据
void ListInsert(ListNode* phead, ListNode* pos, ListDateType x)
{assert(phead);ListNode* newnode = BuyListNode(x);ListNode* prev = pos->prev;prev->next = newnode;newnode->prev = prev;newnode->next = pos;pos->prev = newnode;
}//删除某个位置数据
void ListErase(ListNode* phead, ListNode* pos)
{assert(phead);//别把头删了assert(phead->next != phead);ListNode* prev = pos->prev;ListNode* next = pos->next;prev->next = next;next->prev = prev;free(pos);pos = NULL;
}//改某个值
void ListChange(ListNode* phead, ListDateType source, ListDateType destination)
{assert(phead);ListNode* pos = ListFind(phead, source);pos->date = destination;
}//销毁
void ListDestory(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;ListNode* tail = cur->next;while (tail != phead){free(cur);cur = NULL;cur = tail;tail = tail->next;}free(cur);cur = NULL;if (cur != tail){free(tail);tail = NULL;}
}

今天的内容就到这里了哈!!!

要是认为作者有一点帮助你的话!

就来一个点赞加关注吧!!!当然订阅是更是求之不得!

赠人玫瑰,手有余香=。=!

最后的最后感谢大家的观看!!!

你们的支持是作者写作的最大动力!!!

下期见哈!!!

一篇解双链表(0基础看)(C语言)《数据结构与算法》相关推荐

  1. C语言视频教程免费分享,0基础学C语言

    C语言是一种通用的.过程式的编程语言,广泛用于系统与应用软件的开发.作为计算机编程的基础语言,长期以来它一直是编程爱好者追捧而又比较难学的语言.C语言是一种计算机程序设计语言,它既具有高级语言的特点, ...

  2. 思路不对努力白费!0基础学好C语言编程,必须掌握的学习思路!

    计算机行业发展非常快,大学里的教育基本都跟不上实际的社会需求.如果你所在的学校还在指定大家使用谭浩强的教材,或使用VC6.0来教大家上机实验,那你不妨看看本文,这里有一些建议可以帮助你不会脱离社会太远 ...

  3. 【数据结构】双链表的实现(C语言)

    双链表中的结点包括3个域,一个是存放数据信息的info域,另两个是指阵域,这里用llink和rlink表示,llink指向它的前驱结点,rlink指向它的后继结点. 双链表要掌握以下基本操作: 1.创 ...

  4. 选择大于努力!0基础学好C语言编程,首先要掌握的是什么?

    互联网时代更新换代太快,大学的书本,教育根本跟不上,所以如何用更少的时间掌握最前端的技术,方法很重要. 考虑到这是一个过来人感觉很基础,但是对于初学者又觉得困难重重的问题,我想如果这篇文章要想写得不让 ...

  5. 0基础学习C语言视频

    从0基础开始学习C语言开发的学习视频 给大家提供一个链接:http://www.dsitit.com/?do=kckview&alias=cbiaodashi 这套视频对初学者非常有帮助.

  6. 黑马程序员 C语言数据结构与算法之线性表(链表/栈/队列/顺序表)

    C语言 链表基础知识清晰讲解(黑马) 讲的蛮好,就是音质不太好,有时听不清讲的啥! [黑马]数据结构与算法之线性表(链表/栈/队列/顺序表)[配套源码 嘛蛋,看错了,这是java的... 文章目录 链 ...

  7. 【算法基础】常用的数据结构与算法

    学习了王争老师的数据结构与算法之美之后,比较有感触,他把我们常用的数据结构和算法都讲了一遍,而且讲的还不错.整理汇总一下作为笔记. 一.复杂度分析 非常重要.我们必须掌握,基本上要做到,简单代码能很快 ...

  8. java递归单链表查找中间元素_《数据结构与算法——C语言描述》答案 3.11 查找单链表中的特定元素(递归)...

    转载请注明出处:http://blog.csdn.net/xdz78 #include #include //查找单链表中的特定元素,<数据结构与算法--c语言描述> 3.11 答案 in ...

  9. 太牛了!万文长字:Java基础+网络知识+Linux+数据结构与算法+数据库+系统设计+必会工具+面试指南,一文将Java面试讲解的清清楚楚!

    前言 今天给大家推荐一本PDF文档<Java中高级核心知识全面解析>这份文档总页数:524页.分为八个部分每个部分详细地讲解了核心知识点. 第一部分 扎实的Java基础 (Java基础+容 ...

最新文章

  1. C#中对POP3邮件解码
  2. oracle12c 新特性,12c Oracle数据库新特性汇总
  3. Top10 Web2.0在线生成器
  4. 前端学习(610):js执行过程
  5. sdut 数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
  6. MySql的存储过程
  7. linux期末考试试题4,Linux试题4
  8. POJ 1330 最近公共祖先LCA(Tarjan离线做法)
  9. 13家公司半年报业绩预喜 分布式将成光伏产业发展方向
  10. 电压(电流)运算放大器为什么要增大(减小)输入阻抗?
  11. 露营不在朋友圈,快乐在诗和远方
  12. 微信H5分享 代码和详细配置步骤 js + Java 代码
  13. lehigh计算机就业,2016美国大学计算机专业排名
  14. 运维自动化之ANSIBLE
  15. 告诉你一个真实的二线城市创业生态
  16. 17joys后台代码-初步搭建
  17. echarts 柱状图(1)多条柱状图完成参考标准需求
  18. 2022-2028年中国网约出租车行业市场发展现状及投资策略研究报告
  19. 关于不能用莱布尼兹准则判别级数敛散性时的其中一种方法示例
  20. Jsp+Ssh+Mysql实现的羽毛球馆预约管理系统

热门文章

  1. 解决MyEclipse卡顿慢的情况(速度优化)
  2. 深入解析Apple Review审核规则 韩俊强的博客
  3. 设计模式C++实现40讲(-1)什么是设计模式
  4. uc浏览器app点评
  5. 【AMD】FSR技术的源码编译过程
  6. cdr文件用什么打开?(cdr文件打开方式汇总)
  7. 3D CG软件blender入门教程:手把手教你使用方法
  8. win32汇编语言学习笔记(三)
  9. 前端学习笔记之CSS3新特性3D转换 3.23
  10. hud抬头显示器哪个好_一台车萝卜抬头显示器=安全驾驶+智能语音导航+社交利器...