当前位置: 首页 > news >正文

数据结构-2.9.双链表

一.双链表与单链表的对比:


二.双链表的初始化(带头结点):

1.图解:

2.代码演示:

#include<stdio.h>
#include<stdlib.h>
​
//定义双链表结构体
typedef struct DNode
{int data;struct DNode *prior;//前驱指针即指向前面数据的指针 struct DNode *next;//后继指针即指向后面数据的指针 
}DNode,*DLinklist; //DLinklist与DNode *等价,DLinklist强调链表,DNode *强调结点 
​
//初始化双链表
bool InitDLinkList(DLinklist &L)
{L = (DNode *)malloc( sizeof(DNode) );//分配一个头结点if( L==NULL ) //内存不足,分配失败 {return false;} L->prior = NULL;//头结点的prior(前驱)永远指向NULLL->next = NULL;//头结点之后(后继)暂时还没有结点 return true;
} 
​
//判断双链表是否为空(带头结点)->只需要看第一个结点是否为空即可 
bool Empty(DLinklist L)
{if( L->next == NULL )//代表双链表第一个结点为空,是空双链表{return true;}else{return false;//代表双链表第一个结点不为空,不是空双链表 }
} 
​
int main()
{//初始化双链表 DLinklist L;InitDLinkList(L);//后续代码。。。 return 0;
}

三.双链表的插入:

图解:

此时要p结点之后插入s结点,起初p->next指向y,先把p的下一个结点即y和要插入的结点即s的指向下一个结点的指针对接即s->next = p->next:

之后还需要把p结点的后继结点即p->next的前向指针p->next->prior指向s即p->next->prior = s:

再把要插入的结点即s结点的前驱指针指向p结点即 s->prior = p:

最后把p结点的后继结点指向s即p->next = s:

但对于上述代码,有一个bug,当p结点是最后一个结点时,p->next->prior = s就会报空指针的错,因为

p结点是最后一个结点时p->next指向NULL,因此,严谨的代码如下:对p->next进行空指针判断

  • 按位序插入:找到要插入的位序的前驱结点,在该结点实现后插操作即可

  • 前插操作:由于双链表的特性,可以很方便的找到给定结点的前驱结点,再对前驱结点进行后插操作即可


四.双链表的删除:

图解:

此时要删除p结点的后继结点q,因此要把q结点的下一个结点和p结点连接,即p->next = q->next:

再把要删除的q结点的后继结点即q->next的前驱结点即q->next->prior指向p即q->next->prior = p:

最后再释放要删除的q结点即free(q):free函数要用到头文件#include<stdlib.h>

但上述代码也有bug,如果此时要删除的q结点为双链表最后一个结点,那么q->next就指向NULL,q->next->prior就会报空指针错误,因此对q->next进行空指针判断以增加严谨性:

销毁双链表:每一次删除头结点的后继结点即可

因为比如第一次删除头结点的后继结点即第一个结点,第二次删除时第二个结点就来了第一个位置,相当于头结点的后继结点,删除即可,以此类推,可销毁双链表:


五.双链表的遍历:

1.对于前向遍历(跳过头结点)的循环条件当p->prior == NULL时,说明此时p结点指向的就已经是头结点了,此时跳出循

环,不操作头结点了;

2.对于按位查找,只需要添加一个计数器,用于记录此时指向的哪个位置的元素,当位置和要找的位置匹配时打印即可;

3.对于按值查找,只需要对当前指向的结点和要找的值对比即可,找到了就打印即可;

4.双链表没有随机存取的特性,所以按位查找,按值查找的时间复杂度为O(n),因为只能用循环的方式一个一个对比依次

往后找。


六.总结:


相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 科技引领未来生活——“光影漫游者”展览馆应用—轻空间
  • 每日学习一个数据结构-布隆过滤器Bloom Filter
  • 数据结构:二叉树(2)
  • Linux 清空redis缓存及查询key值
  • 修改 Visual Studio 的主题颜色、背景颜色、字体
  • 分布式计算技术是什么?在数据集成值得作用?
  • Java项目实战II基于Java+Spring Boot+MySQL的车辆管理系统(开发文档+源码+数据库)
  • Stable Cascade | ComfyUI API 工作流格式优化
  • 教你如何在微信小程序中轻松实现人脸识别功能
  • STM32——SPI
  • JVM基础篇学习笔记
  • Stable Diffusion不同部件拆分详解!
  • nethogs显示每个进程所使用的带宽
  • Git可视化工具和基础命令
  • Linux 安装Docker
  • canvas 五子棋游戏
  • ECS应用管理最佳实践
  • Mybatis初体验
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Sublime text 3 3103 注册码
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 再次简单明了总结flex布局,一看就懂...
  • 在weex里面使用chart图表
  • 【运维趟坑回忆录 开篇】初入初创, 一脸懵
  • gunicorn工作原理
  • # 飞书APP集成平台-数字化落地
  • #QT(串口助手-界面)
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (Spark3.2.0)Spark SQL 初探: 使用大数据分析2000万KF数据
  • (多级缓存)缓存同步
  • (离散数学)逻辑连接词
  • (力扣)1314.矩阵区域和
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (学习总结16)C++模版2
  • (原)Matlab的svmtrain和svmclassify
  • (转)Linq学习笔记
  • (自用)learnOpenGL学习总结-高级OpenGL-抗锯齿
  • ***检测工具之RKHunter AIDE
  • .360、.halo勒索病毒的最新威胁:如何恢复您的数据?
  • .a文件和.so文件
  • .net core IResultFilter 的 OnResultExecuted和OnResultExecuting的区别
  • .NET Framework .NET Core与 .NET 的区别
  • .NET(C#) Internals: as a developer, .net framework in my eyes
  • .Net6 Api Swagger配置
  • .NET中分布式服务
  • ??myeclipse+tomcat
  • @private @protected @public
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [2021ICPC济南 L] Strange Series (Bell 数 多项式exp)
  • [2023-年度总结]凡是过往,皆为序章
  • [⑧ADRV902x]: Digital Pre-Distortion (DPD)学习笔记
  • [AIGC 大数据基础]hive浅谈