带头双向循环链表的模拟实现
目录
1.简介
2.源码分享
3.链表模拟实现
3.1 动态申请一个节点
3.2初始化链表,创建头节点
3.3实现尾插
3.4 实现头插
3.5 实现头删
3.6 尾删
3.7打印链表
3.8实现查找
3.9 实现pos位置前插入数据
3.10 删除 pos 位置的节点
3.11 销毁链表
1.简介
带头双向循环链表:结构在链表中最为复杂,一般用来单独存放数据,实际中使用最多的链表结构。但是其只是结构复杂,使用起来其实比较简便。
2.源码分享
1. 带头双向循环链表源码 DList · 斯文/Date Stucture - 码云 - 开源中国 (gitee.com)
2. 不带头单向链表 博客(11条消息) 单链表详细解析,详细图解加代码实现,轻松拿捏。_杨斯文。的博客-CSDN博客
源码: Single linked list/Single linked list · 斯文/Date Stucture - 码云 - 开源中国 (gitee.com)
3.链表模拟实现
3.1 动态申请一个节点
typedef int DListdatatype;typedef struct DListNode
{DListdatatype data;struct DListNode* prev;struct DListNode* next;}DListNode;
由于我们需要做到双向循环,我们定义的结构体变量中需要两个指针,一个用来指向下一个,一个指向前一个。
// 创造节点
DListNode* BuyListNode(DListdatatype x)
{DListNode* Node = (DListNode*)malloc(sizeof(DListNode));Node->data = x;Node->next = NULL;Node->prev = NULL;return Node;
}
动态申请节点,返回申请的节点地址,将不确定的指针都先置空,避免出现野指针。
3.2初始化链表,创建头节点
// 初始化头结点
DListNode* ListInit()
{DListNode * head = BuyListNode(0);head->next = head;head->prev = head;
}
创造的头节点,并不使用数据,括号中的值可以随意输入。
3.3实现尾插
// 尾插
void PushBack(DListNode* p, DListdatatype x)
{assert(p);DListNode* newnode = BuyListNode(x);DListNode* tail = p -> prev;tail->next = newnode;newnode->prev = tail;newnode->next = p;p->prev = newnode;ListInsert(p, x); 利用pos前插入函数
}
其实函数的实现是比较简单的,记得处理好指针细节。
3.4 实现头插
// 头插
void ListPushFront(DListNode* p, DListdatatype x)
{assert(p);DListNode* newnode = BuyListNode(x);DListNode* cur = p->next;newnode->next = cur;newnode->prev = p;cur->prev = newnode;p->next = newnode;//ListInsert(p->next, x);
}
比较简单,不多做分析,处理好细节就可以了。
3.5 实现头删
// 头删
void ListPopFront(DListNode* p)
{assert(p);if (p->next == p){printf("链表已空\n");return;}else{DListNode* next = p->next;p->next = next->next;next->next->prev = p;free(next);}/*ListErase(p->next);*/// 需要多判断一步是否为空,不空再删
}
3.6 尾删
// 尾删void ListPopBack(DListNode* p)
{assert(p);if (p->next == p){printf("链表已空\n");return;}else{DListNode* tail = p->prev;tail->prev->next = p;p->prev = tail->prev;free(tail);}
/* ListErase(p->prev); */ // 需要多判断一步是否为空,不空再删
}
3.7打印链表
// 打印
void ListPrint(DListNode* p)
{DListNode* cur = p->next;while (cur != p){printf("%d ", cur->data);cur = cur->next;}printf("\n");
}
由于是循环链表,打印链表和后续的查找函数的循环参数的判断条件就不可以是 NULL,我们取头节点后的第一个节点,遍历节点,循环时,等于头节点,即遍历了一遍链表,跳出循环。
3.8实现查找
//查找 x, 返回地址
DListNode* ListFind(DListNode* p, DListdatatype x)
{assert(p);DListNode* cur = p->next;while (cur != p){if (cur->data == x){printf("找到了\n");return cur;}cur = cur->next;}printf("没找到\n");return NULL;
}
3.9 实现pos位置前插入数据
// 在pos 位置前插入值 void ListInsert(DListNode* pos, DListdatatype x)
{DListNode* newnode = BuyListNode(x);DListNode* prev = pos->prev;newnode->next = pos;pos->prev = newnode;prev->next = newnode;newnode->prev = prev;}
注意pos后一个节点,注意替换顺序,避免丢失节点。
同时,我们可以使用这个函数来实现 ,头插,尾插
头插 : ListInsert(p->next, x); 在第一个数据节点前再插入新节点。
尾插:ListInsert(p, x); 利用pos前插入函数
尾插复杂一些
可以理解为,在头节点前插入一个节点,等于尾插。
3.10 删除 pos 位置的节点
// 删除pos 位置的 节点
void ListErase(DListNode* pos)
{assert(pos);pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);
}
将pos 的前后节点链接到一起。
同理,可以使用这个函数实现头删,尾删
头删 :ListErase( p ->next) ;
尾删 : ListErase( p->prev);
3.11 销毁链表
// 销毁链表void ListDestroy(DListNode* p)
{assert(p);DListNode* cur = p->next;while (cur != p){DListNode* next = cur->next;free(cur);cur = next;}free(p);
}
需要注意循环链表的遍历条件 ,逐步销毁。
本篇博客到此结束,谢谢观看!
带头双向循环链表的模拟实现相关推荐
- 一文搞定带头双向循环链表
什么是链表 链表的种类 最经典的两种链表 带头双向循环链表详细 什么是链表 在数据结构线性表里 除了顺序表 还有一种我们不得不说 他就是链表 链表的关键就是指针 创建出一块节点空间存储着 一边是val ...
- 数据结构与算法 | 带头双向循环链表
上一节里实现的是最简单的链表,在实际中那种链表不会单独用来存储数据,更多是作为其他数据结构的子结构,如图的邻接表等.而比较常用的就是带头双向循环链表. 通过对比我们可以看出有三个不同,多了头节点,链表 ...
- 比特数据结构与算法(第二章收尾)带头双向循环链表的实现
1.链表的分类 链表的分类 ① 单向或者双向 ② 带头或者不带头 ③ 循环或者非循环 常用的链表: 根据上面的分类我们可以细分出8种不同类型的链表,这么多链表我们一个个讲解这并没有意义.我们实际中最常 ...
- 【数据结构】链表:带头双向循环链表的增删查改
本篇要分享的内容是带头双向链表,以下为本片目录 目录 一.链表的所有结构 二.带头双向链表 2.1尾部插入 2.2哨兵位的初始化 2.3头部插入 2.4 打印链表 2.5尾部删除 2.6头部删除 2. ...
- 数据结构-带头双向循环链表(增删查改详解)
在上一篇博客中,详细介绍了单链表的增删查改,虽然单链表的结构简单,但是用起来却不是那么顺手.因此根据单链表的种种缺点,这篇博客所介绍的带头双向循环链表将会带来极大的优化. 上图就是带头双向循环链表的主 ...
- 初阶数据结构之带头+双向+循环链表增删查实现(三)
文章目录 @[TOC](文章目录) 前言 一.带头双向循环链表的初始化 1.1带头双向循环链表的结构体定义 1.2初始化代码的实现 二.带头+双向+循环链表的增功能实现 2.1头插代码的实现 2.2尾 ...
- 数据结构:带头双向循环链表——增加、删除、查找、修改,详细解析
读者可以先阅读这一篇:数据结构--单链表的增加.删除.查找.修改,详细解析_昵称就是昵称吧的博客-CSDN博客,可以更好的理解带头双向循环链表. 目录 一.带头双向循环链表的处理和介绍 1.带头双向循 ...
- 数据结构篇 --- 带头双向循环链表增删查改
简述:有了前篇单链表的增删查改的基础 也是出于带头双向循环链表本身的优势 双链表的增删就变得格外简单.让我们一起来体验一下. 目录 带头双向循环链表图解: 带头双向循环链表基本结构: 带头双向循环链 ...
- 【数据结构】-关于带头双向循环链表的增删查改
作者:低调 作者宣言:写好每一篇博客 文章目录 前言 一.带头双向循环链表的实现 1.1创建返回链表的头结点 1.2开辟一个新的结点 1.3双向链表的销毁 1.4双向链表的打印 1.5双向链表尾插 1 ...
最新文章
- Linux系统设置全局的默认网络代理
- python动态语言解释_python是动态语言吗
- 持续集成之 Jenkins 钉钉通知(八)
- Cannot find module 'express'
- 易语言自定义数据类型转c,一步一步跟我学易语言之自定义数据类型
- stm32f401 边沿捕获_STM32_capture 基于 设计的输入捕获实验,通过对边沿跳变的采集,得到外部接口 据。 SCM 单片机开发 261万源代码下载- www.pudn.com...
- python post上传大文件分片上传_基于七牛 用python实现分片上传 创建文件报错701...
- 通用汽车研发中心最新提出:3D车道线检测新方法
- 微信小程序开发:禁止输入表情的控制,验证方法,光标控制
- springboot之idea多模块
- esp8266 SOC方案经过半年沉淀之后再度重启二
- 如何快速播放CSF视频文件的办法
- oracle根据身份证号码计算年龄
- Kotlin中三元运算符
- 参考《机器学习实战》高清中文PDF+高清英文PDF+源代码
- html语言剖析十六 调色原理
- uni-app使用 getUserInfo 报错 fail can only be invoked by user TAP gesture 解决方法
- android10全面屏手势 操作图,丨系统设计丨ZUI 10加入更多全面屏手势
- 微信小程序绘制地图轨迹线路
- 新版傻妞升级之后 登录 查询无反应
热门文章
- android hid 音量,android Hid 实现注意事项
- GitChat · 架构 | 如何从零开始搭建高性能直播平台?
- CSU 1224: ACM小组的古怪象棋(BFS)
- linux查进程位置的命令
- linux 监听终端输入法,xinit 终端中文输入法
- ssh远程打开ubuntu的vino-server
- java编辑遗忘曲线代码_通过excel vba 实现艾宾浩斯遗忘曲线的复习提醒
- 使用百度地图Web服务API查询地点的经纬度信息
- vin端口是什么意思_振荡器基础1——为什么振荡器需要正反馈?什么是LC自激振荡器?...
- skywalking实战--agent异常日志监控