【数据结构】带头双向循环链表的实现
🌇个人主页:平凡的小苏
📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情
🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html
🚀数据结构专栏:https://blog.csdn.net/vhhhbb/category_12211053.html
家人们更新不易,你们的👍点赞👍和⭐关注⭐真的对我真重要,各位路过的友友麻烦多多点赞关注,欢迎你们的私信提问,感谢你们的转发!
关注我,关注我,关注我,你们将会看到更多的优质内容!!
1、带头循环双向链表
我们在单链表中,有了next指针,这使得我们要查找下一节点的时间复杂度为O(1)。可是如果我们要查找的是上一节点的话,那最坏的时间复杂度就是O(n)了,因为我们每次都要从头开始遍历查找。
为了克服单向性这一缺点,我们的老科学家们,设计出了双向链表。双向链表是在单链表的每个结点中,再设置一个指向其前驱结点的指针域。所以再双向链表中的结点都有两个指针域,一个指向直接后继,另一个指向直接前驱。
既然单链表可以有循环链表,那么双向链表也可以有循环双向链表。(如下图所示)
2、双向循环链表函数接口的实现
2.1、双向循环链表的结构
typedef int LTDataType;
typedef struct ListNode
{LTDataType _data;//数据struct ListNode* _next;//后继指针struct ListNode* _prev;//前驱指针
}ListNode;
2.2、初始化双向循环链表
ListNode* ListCreate()
{ListNode* phead = (ListNode*)malloc(sizeof(ListNode));if (phead == NULL){perror("malloc Fail:");exit(-1);}phead->_next = phead;phead->_data = -1;phead->_prev = phead;return phead;
}
由于是带头循环链表,我们需要malloc一个头节点出来,当链表是空的时候,前驱指针和后继指针都指向头结点。
2.3、双向循环链表的插入
// 创建返回链表的头结点.
ListNode* BuyListNode(LTDataType x)
{ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));if (newhead == NULL){perror("malloc fail:");exit(-1);}newhead->_data = x;newhead->_next = NULL;newhead->_prev = NULL;return newhead;
}
//双链表插入
void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* newhead = BuyListNode(x);//该函数是创建新节点的函数ListNode* Prev = pos->_prev;Prev->_next = newhead;newhead->_prev = Prev;newhead->_next = pos;pos->_prev = newhead;
}
注:由于我们是在pos的前面插入一个结点,那么我们就应该保存上一个结点。
插入算法的具体操作步骤:
1.Prev->_next = newhead;
2.newhead->_prev = Prev;
3.newhead->_next = pos;
4.pos->_prev = newhead;
2.4、双向循环链表的删除操作
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{assert(pos);//删除前pos不能为空assert(!ListEmpty(pos));//链表不为空才能删ListNode* ne = pos->_next;//保存pos位置的后一个结点pos->_prev->_next = ne;//删除结点的具体操作ne->_prev = pos->_prev;free(pos);//释放
}
2.5、双向循环链表的判空
bool ListEmpty(ListNode* pHead)
{assert(pHead);return pHead->_next == pHead;如果头结点的下一个结点也等于头结点的话那么链表为空
}
2.6、双向循环链表的打印
// 双向链表打印
void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->_next;while (cur != pHead){printf("%d ", cur->_data);cur = cur->_next;}printf("\n");
}
2.7、双向循环链表的销毁
// 双向链表销毁
void ListDestory(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->_next;while (cur != pHead)//链表要遍历释放{ListNode* ne = cur->_next;free(cur);cur = ne;}free(pHead);pHead = NULL;
}
3、源代码
由于头插、头删、尾插、尾删可以用双向循环链表的插入和删除操作复用,这里直接放置源代码。
3.1、DList.c
#include"DSList.h"
// 创建返回链表的头结点.
ListNode* BuyListNode(LTDataType x)
{ListNode* newhead = (ListNode*)malloc(sizeof(ListNode));if (newhead == NULL){perror("malloc fail:");exit(-1);}newhead->_data = x;newhead->_next = NULL;newhead->_prev = NULL;return newhead;
}
ListNode* ListCreate()
{ListNode* phead = (ListNode*)malloc(sizeof(ListNode));if (phead == NULL){perror("malloc Fail:");exit(-1);}phead->_next = phead;phead->_data = -1;phead->_prev = phead;return phead;
}
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newhead = BuyListNode(x);ListNode* tail = pHead->_prev;newhead->_prev = tail;tail->_next = newhead;newhead->_next = pHead;pHead->_prev = newhead;//ListInsert(pHead, x);
}
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* newhead = BuyListNode(x);ListNode* first = pHead->_next;newhead->_prev = pHead;pHead->_next = newhead;newhead->_next = first;first->_prev = newhead;//ListInsert(pHead->_next, x);
}
// 双向链表在pos的前面进行插入//判空
bool ListEmpty(ListNode* pHead)
{assert(pHead);return pHead->_next == pHead;
}
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{assert(pHead);assert(!ListEmpty(pHead));ListNode* tail = pHead->_prev;ListNode* prevtail = tail->_prev;prevtail->_next = pHead;pHead->_prev = prevtail;free(tail);//ListErase(pHead->_prev);
}
// 双向链表头删
void ListPopFront(ListNode* pHead)
{assert(pHead);assert(!ListEmpty(pHead));ListNode* first = pHead->_next;pHead->_next = first->_next;first->_next->_prev = pHead;free(first);//ListErase(pHead->_next);
}
//双链表插入
void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* newhead = BuyListNode(x);ListNode* Prev = pos->_prev;Prev->_next = newhead;newhead->_prev = Prev;newhead->_next = pos;pos->_prev = newhead;
}
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{assert(pHead);ListNode* cur = pHead->_next;while (cur != pHead){if (cur->_data == x){return cur;}cur = cur->_next;}return NULL;
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{assert(pos);assert(!ListEmpty(pos));ListNode* ne = pos->_next;pos->_prev->_next = ne;ne->_prev = pos->_prev;free(pos);
}
// 双向链表打印
void ListPrint(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->_next;while (cur != pHead){printf("%d ", cur->_data);cur = cur->_next;}printf("\n");
}
// 双向链表销毁
void ListDestory(ListNode* pHead)
{assert(pHead);ListNode* cur = pHead->_next;while (cur != pHead){ListNode* ne = cur->_next;free(cur);cur = ne;}free(pHead);pHead = NULL;
}
3.2、DList.h
#include<stdio.h>
#include<assert.h>
#include<stdbool.h>
#include<stdlib.h>
// 带头+双向+循环链表增删查改实现
typedef int LTDataType;
typedef struct ListNode
{LTDataType _data;struct ListNode* _next;struct ListNode* _prev;
}ListNode;// 创建返回链表的头结点.
ListNode* ListCreate();
// 双向链表销毁
void ListDestory(ListNode* pHead);
// 双向链表打印
void ListPrint(ListNode* pHead);
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x);
// 双向链表尾删
void ListPopBack(ListNode* pHead);
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x);
// 双向链表头删
void ListPopFront(ListNode* pHead);
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x);
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x);
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos);
//判空
bool ListEmpty(ListNode* pHead);
好了!!!小编的分享到这里就结束了,有什么不足的地方请大佬多多指教!
相关文章:
【数据结构】带头双向循环链表的实现
🌇个人主页:平凡的小苏 📚学习格言:别人可以拷贝我的模式,但不能拷贝我不断往前的激情 🛸C语言专栏:https://blog.csdn.net/vhhhbb/category_12174730.html 🚀数据结构专栏ÿ…...
软件开发的权限系统功能模块设计,分享主流的九种常见权限模型
软件系统的权限控制几乎是非常常见且必备的,这篇文章整理下常见的九种模型,几乎基本够你用了,主流的权限模型主要有以下9种: 1、ACL模型 访问控制列表 2、DAC模型 自主访问控制 3、MAC模型 强制访问控制 4、ABAC模型 基于属性的访…...
CSS3-数据可视化
2D动画 - transform CSS3 transform属性允许你旋转,缩放,倾斜或平移给定元素。 Transform是形变的意思(通常也叫变换),transformer就是变形金刚 常见的函数transform function有: 平移:transl…...
硬件系统工程师宝典(15)-----PCB上的EMC设计,“拿捏了”
各位同学大家好,欢迎继续做客电子工程学习圈,今天我们继续来讲这本书,硬件系统工程师宝典。上篇我们说到PCB常用的多层板叠层结构,综合成本、性能、需求考虑选择不同的叠层结构。今天我们来看看为提高EMC性能,在PCB设计…...
vue3滚动条滚动后元素固定
代码地址:https://gitee.com/zzhua195/easyblog-web-vuee Framework.vue 在这个布局组件中,监听main的滚动事件,获取滚动的距离,将它存入store,以便其它组件能够共享,监听到 <template><div c…...
新吲哚菁绿染料IR-825 NHS,IR825 NHS ester,IR825 SE,IR-825 活性酯,用于科研实验研究和临床
IR825 NHS理论分析:中文名:新吲哚菁绿-琥珀酰亚胺酯,IR-825 琥珀酰亚胺酯,IR-825 活性酯英文名:IR825 NHS,IR-825 NHS,IR825 NHS ester,IR825 SECAS号:N/AIR825 NHS产品详…...
GO语言--接口(interface)的定义及使用
接口定义 接口也是一种数据类型,它代表一组方法的集合。 接口是非侵入式的。即接口设计者无需知道接口被哪些类型实现,而接口使用者只需知道实现怎样的接口,并且无须指明实现哪一个接口。编译器在编译时就会知道哪个类型实现哪个接口&#…...
【Python语言基础】——Python MongoDB 查询
Python语言基础——Python MongoDB 查询 文章目录 Python语言基础——Python MongoDB 查询一、Python MongoDB 查询一、Python MongoDB 查询 筛选结果 在集合中查找文档时,您能够使用 query 对象过滤结果。 find() 方法的第一个参数是 query 对象,用于限定搜索。 实例 查找地…...
第十四届蓝桥杯模拟赛【第三期】Python
1 进制转换 问题描述 请找到一个大于 2022 的最小数,这个数转换成十六进制之后,所有的数位(不含前导 0)都为字母(A 到 F)。 请将这个数的十进制形式作为答案提交。 答案:2730 def ch…...
windows 下docker 安装clickhouse
docker 下载https://www.docker.com/products/docker-desktop/将下载下来的Docker Desktop Installer.exe文件双击进行安装即可,安装完成后,任务栏会出现一个蓝色的小鲸鱼图标(注意安装完成后可能会重启系统)Docker Desktop如果出…...
【华为OD机试真题 JAVA】TLV编码问题
标题:TLV编码问题 | 时间限制:1秒 | 内存限制:262144K | 语言限制:不限 TLV编码是按TagLengthValue格式进行编码的,一段码流中的信元用tag标识,tag在码流中唯一不重复,length表示信元value的长度,value表示信元的值,码流以某信元的tag开头,tag固定占一个字节,lengt…...
深度学习 Day26——使用Pytorch实现猴痘病识别
深度学习 Day26——使用Pytorch实现猴痘病识别 文章目录深度学习 Day26——使用Pytorch实现猴痘病识别一、前言二、我的环境三、前期工作1、设置GPU导入依赖项2、导入猴痘病数据集3、划分数据集四、构建CNN网络五、训练模型1、设置超参数2、编写训练函数3、编写测试函数4、正式…...
redis简单介绍
对于一名前端工程师,想要进阶成为全栈工程师,redis技术是我们一定需要掌握的。作为当前非关系型数据库Nosql中比较热门的key-value存储系统,了解redis的原理和开发是极其重要的。本文我会循序渐进的带领大家一步步认识redis,使用r…...
Understanding services:理解服务(Service)
文章目录背景1. 准备工作2. ros2 service list 命令3. ros2 service type 命令3.1 ros2 service list -t 命令4. ros2 service find 命令5. ros2 interface show 命令6. ros2 service call 命令参考官方文档: Understanding services背景 服务(Service&…...
【链表OJ题(五)】合并两个有序链表
📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:数据结构 🎯长路漫漫浩浩,万事皆有期待 文章目录链表OJ题(五)1. 合并…...
C++ Primer第五版_第三章习题答案(1~10)
文章目录练习3.1练习3.2一次读入一行一次读入一个词练习3.3练习3.4大的字符串长度大的字符串练习3.5未隔开的隔开的练习3.6练习3.7练习3.8练习3.9练习3.10练习3.1 使用恰当的using 声明重做 1.4.1节和2.6.2节的练习。 // 1.4.1 #include <iostream>using std::cin; using…...
小样本学习
机器学习就是从数据中学习,从而使完成任务的表现越来越好。小样本学习是具有有限监督数据的机器学习。类似的,其他的机器学习定义也都是在机器学习定义的基础上加上不同的限制条件衍生出来。例如,弱监督学习是强调在不完整、不准确、有噪声、…...
python打包成apk界面设计,python打包成安装文件
大家好,给大家分享一下如何将python程序打包成apk文件,很多人还不知道这一点。下面详细解释一下。现在让我们来看看! 1、如何用python制作十分秒加减的apk 如何用python制作十分秒加减的apk?用法:. apk包放入apk文件目录,然后输入…...
pytorch转onnx踩坑日记
在深度学习模型部署时,从pytorch转换onnx的过程中,踩了一些坑。本文总结了这些踩坑记录,希望可以帮助其他人。 首先,简单说明一下pytorch转onnx的意义。在pytorch训练出一个深度学习模型后,需要在TensorRT或者openvin…...
极智AI | GPT4来了,ChatGPT又该升级了
欢迎关注我,获取我的更多经验分享 大家好,我是极智视界,本文介绍一下 GPT4来了,ChatGPT又该升级了,更多的是个人思考。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https://t.zsxq.com/0aiNxERDq 从 ChatGPT 发布 (2022年11月30日) 到…...
智能优化算法之灰狼优化算法(GWO)的实现(Python附源码)
文章目录一、灰狼优化算法的实现思路1、社会等级结构分级2、包围猎物3、攻击猎物4、搜索猎物二、算法步骤三、实例一、灰狼优化算法的实现思路 灰狼优化算法(Grey Wolf Optimizer,简称GWO)是由Seyedali Mirjalili等人于2014年提出的一种群智…...
leetCode热题10-15 解题代码,思路
前言 计划做一系列算法题的文章,因为自己这块确实比较薄弱,但又很重要!写这篇文章前,我已经刷了一本剑指offer,leetcode top150道,牛客某题库106道 这个样子吧,感觉题量算是入门了吧࿱…...
同步辐射GISAXS和GIWAXS的原理及应用领域
同步辐射GISAXS和GIWAXS是两种常用的同步辐射X射线衍射技术,它们在材料科学、化学、生物学、物理学等领域中广泛应用。本文将从原理、实验方法和应用三个方面,对同步辐射GISAXS和GIWAXS进行描述和比较。 一、原理 GISAXS和GIWAXS都是利用X射线与样品相互…...
OpManager 进行网络性能管理
计算机网络构成了任何组织的 IT 基础架构的支柱。由于企业严重依赖基于互联网的应用程序,由于网络相关问题,最终用户不受影响非常重要。因此,借助网络管理解决方案监控和提高网络性能对于保持企业始终正常运行至关重要。这将确保维护服务级别…...
面试被问到向上转型和向下转型时,怎么回答?
目录 前置小知识 1、向上转型 补充:向上转型的三种情况 2、向下转型 使用关键字:instanceof 3、转型带来了什么好处 前置小知识 java中的继承,我们简单回顾一下 通过java中的继承机制,可以实现一个类继承另一个类ÿ…...
加密月解密:概述,基础篇
加密月解密:概述,基础篇 2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测开 测开的话,你就得学数据库,sql,oracle&…...
DC-DC升压模块隔离高压稳压电源直流变换器12v24v48v转600V1000V1100V1500V2000V3000V
特点● 效率高达 80%● 2*2英寸标准封装● 单双电压输出● 价格低● 大于600V高压,稳压输出● 工作温度: -40℃~85℃● 阻燃封装,满足UL94-V0 要求● 温度特性好● 可直接焊在PCB 上应用HRB W1~25W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&am…...
pandas数据分析(三)
书接pandas数据分析(二) 文章目录DataFrame数据处理与分析处理超市交易数据中的异常值处理超市交易数据中的缺失值处理超市交易数据中的重复值使用数据差分查看员工业绩波动情况使用透视表与交叉表查看业绩汇总数据使用重采样技术按时间段查看员工业绩Da…...
cpu performance profiling
精彩文章分享1. android performanceAndroid 性能分析工具介绍 (qq.com)手机Android存储性能优化架构分析 (qq.com)抖音 Android 性能优化系列:启动优化之理论和工具篇 (qq.com)那些年,我们一起经历过的 Android 系统性能优化 (qq.com)Android卡顿&#…...
vue2启动项目npm run dev报错 Error: Cannot find module ‘babel-preset-es2015‘ 修改以及问题原因
报错内容如下图: 说找不到模块 babel-preset-es2015。 在报错之前,我正在修改代码,使用 ElementUI 的按需引入方式,修改了 babel.config.js 。 注意:vue/cli 脚手架4版本已经使用了 babel7 ,所以项目中…...
直播视频素材/seo关键词排名技术
磁盘管理:RAIDRedundent Aarry of Inexpensive DisksRedundent Aarry of Indepedent Disks目的:高性能(读、写)、可靠(冗余)级别:Level,用于描述磁盘不同组合逻辑Raid0: 条带Raid1: 镜像Raid10就是将Raid1和Raid0按某种方式连接起…...
无锡seo网站管理/扬州网络推广哪家好
Samba原理和配置 个人原创,转载请注明,否则追究法律责任。 一,原理及安装 1,Samba是在Linux和UNIX系统上实现在局域网上共享文件一种通信协议,它为局域网内的不同计算机之间提供文件等资源的共享服务。 2,Samba访问…...
网站gif图标/网络营销策划目的
基础规范【建议】使用InnoDB存储引擎【强制】无特殊要求必须使用UTF8字符集【强制】数据表、数据字段必须加入中文注释【强制】禁止使用存储过程、视图、触发器、Event。特殊情况申请评审【强制】不在数据库做运算,cpu计算务必移至业务层命名规范【建议】 命名使用具…...
河南省城乡和住房建设厅/班级优化大师是干什么用的
目录概念:通俗理解:可重入锁的工作原理:ReenTrantLock可重入锁和synchronized的区别:ReentrantLock源码分析:可重入锁代码演示:概念: Reentrant Re entrant,Re是重复、又、再的意思࿰…...
网站编程培训学校招生/搜索引擎优化文献
提交一个 服务器请求(support request) 然后在你的服务请求中同时提供下面的信息。 Confluence 服务器 登录 Confluence 然后访问管理员控制台。 将 系统信息(System Information)页面的中内容进行截图,或者保存页面为…...
建站工具推荐/百度竞价推广培训
楼经济,还能印多久钞票。...