C语言双向链表
文章目录
- 前言
- 双向链表
- 链表头结点的创建
- 节点尾插与尾删
- 节点头插与头删
- 特定位置插入或删除节点
- 链表节点查找
- 双向链表的销毁
- 链表的打印
前言
假期时间因为为学校开学考试做准备所以一直没更新博客,今天开始博客会陆续更新。
双向链表
之前我们说过了顺序表和单链表,这次介绍双向链表,双向链表在使用上要比单链表简单,结构比单链表复杂一些,需要两个指针域,其结构如下图,其中头结点数据域不动(不要存放指针长度一类因为有时候我们不确定链表节点数据类型,如果是char类型而节点数大于128,那么就会出现bug),带有头结点可方便对其操作。
双向链表节点代码如下:
typedef int LTDataType;
typedef struct ListNode {struct ListNode* prev;struct ListNode* next;LTDataType data;
}LTNode;
与单链表相同无非是双向链表的增删改查。
链表头结点的创建
ListNode* ListCreate()
{ListNode* head = (ListNode*)malloc(sizeof(ListNode));head->next = head;head->prev = head;return head;
}
这里别忘了是双向链表,要给两个指针都赋值,因为是头结点(PS:头结点数据域一般是垃圾值)所以就指向自己。
节点尾插与尾删
// 双向链表尾插
void ListPushBack(ListNode* pHead, LTDataType x)
{ListNode* tail = pHead->prev;ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));newnode->data = x;tail->next = newnode;newnode->prev = tail;newnode->next = pHead;pHead->prev = newnode;
}
这里就体现出双向链表的优势,我们不用遍历就可以直接找到链表的尾结点。
// 双向链表尾删
void ListPopBack(ListNode* pHead)
{ListNode* tail = pHead->prev;ListNode* TailPrev = tail->prev;free(tail);TailPrev->next = pHead;pHead->prev = TailPrev;
}
尾插时不要忘了让节点指向头结点。
节点头插与头删
// 双向链表头插
void ListPushFront(ListNode* pHead, LTDataType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));newnode->data = x;newnode->next = pHead->next;pHead->next->prev = newnode;pHead->next = newnode;newnode->prev = pHead;
}
这里注意哈,链表的头插与头删是在头结点之后位置进行,这里例出一幅头插图作为参考(艺术细胞为0后续可能解锁画图软件,这里先凑合看)。
// 双向链表头删
void ListPopFront(ListNode* pHead)
{ListNode* cur = (ListNode*)malloc(sizeof(ListNode));cur = pHead->next;pHead->next = cur->next;cur->next->prev = pHead;free(cur);
}
头插和头删要注意顺序,否则可能找不到头结点的下一个节点。
特定位置插入或删除节点
// 双向链表在pos的前面进行插入
void ListInsert(ListNode* pos, LTDataType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));newnode->data = x;newnode->next = pos;newnode->prev = pos->prev;pos->prev->next = newnode;pos->prev = newnode;
}
// 双向链表删除pos位置的节点
void ListErase(ListNode* pos)
{pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);
}
这里还是注意一下代码顺序无其他重点。
链表节点查找
// 双向链表查找
ListNode* ListFind(ListNode* pHead, LTDataType x)
{ListNode* cur = pHead->next;while (cur != pHead){if (cur->data == x)return cur;cur = cur->next;}return pHead;
}
若最后没有找到该数值则返回头结点。
双向链表的销毁
// 双向链表销毁
void ListDestory(ListNode* pHead)
{ListNode* newhead = pHead->next;ListNode* cur = newhead->next;while (cur->next!=pHead){free(newhead);newhead = cur;cur = newhead->next;}free(pHead);pHead == NULL;
}
这里别忘了最后删除并置空头结点,置空头结点的原因是使用者在主函数还有头结点的地址,但此时头结点已被释放(野指针),若再次调用头结点则可能出现bug。
链表的打印
// 双向链表打印
void ListPrint(ListNode* pHead)
{ListNode* newnode = pHead->next;while (newnode!=pHead){printf("%d ", newnode->next->data);newnode = newnode->next;}
}
比较简单,不做赘述。
双向链表许多函数的while循环是判断其节点是否与头结点相等,而不是其节点是否为空,这里要注意与单链表区分,最后代码其实还应该加上断言(assert)函数判断是否为空,但博主这里没有加(是故意的还是不小心的)。
这里纯粹是懒得加了,这个习惯不是很好,大家不要学我,最好还是自己加一下。
最后期待你的三连,若有错误欢迎私信或评论区指出。
相关文章:

C语言双向链表
文章目录 前言双向链表链表头结点的创建节点尾插与尾删节点头插与头删特定位置插入或删除节点链表节点查找双向链表的销毁 链表的打印 前言 假期时间因为为学校开学考试做准备所以一直没更新博客,今天开始博客会陆续更新。 双向链表 之前我们说过了顺序表和单链表…...

朋友圈大佬都去读研了,这份备考书单我码住了
作者简介: 辭七七,目前大二,正在学习C/C,Java,Python等 作者主页: 七七的个人主页 文章收录专栏: 七七的闲谈 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!💖…...

JavaScript设计模式(五)——发布订阅模式、桥接模式、组合模式
个人简介 👀个人主页: 前端杂货铺 🙋♂️学习方向: 主攻前端方向,正逐渐往全干发展 📃个人状态: 研发工程师,现效力于中国工业软件事业 🚀人生格言: 积跬步…...

prize_p1
文章目录 解题过程代码审计思路问题解决数组绕过preg_match__destruct的触发修改phar文件以及签名phar://支持的后缀 题解方法一(数组绕过)方法二(gzip绕过) 解题过程 源代码 <META http-equiv"Content-Type" conte…...
Acwing 3534. 矩阵幂 3535. C翻转
3534. 矩阵幂 - AcWing题库 思路:模拟,当然,k次幂可以用快速幂优化,这里懒了 #include <iostream> #include <vector> using namespace std;vector<vector<int>> mul(int n, vector<vector<int>…...

Spring Cloud:构建微服务的最佳实践
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

时间序列场景下多种数据填充算法实践与对比分析
在时间序列建模任务中,模型往往对于缺失数据是比较敏感的,大量的缺失数据甚至会导致训练出来的模型完全不可用,在我前面的博文中也有写到过数据填充相关的内容,感兴趣的话可以自行移步阅读即可: 《python 基于滑动平均…...

Mysql开启binlog
本案例基于mysql5.7.16实验 1、在linux中进入mysql查询binlog是否打开,执行命令如下: mysql -u root -p 2、查询binlog是否开启命令如下,如果log_bin为OFF则证明mysql的binlog没有打开 show variables like %log_bin%; 3、退出mysql终端&…...

【Java Web】HTML 标签 总结
目录 1.HTML 2.标签 1. head 标签 1.图标 2.样式居中 2. body 标签 1.注释 : 2.加载图片 3.加载视频 效果 4.区域 效果 5.上下跳转,页面跳转 效果 6.表格 效果 7.有序列表,无序列表 效果 8.登录 效果 9.按钮 10.多选框…...
前端面试的话术集锦第 4 篇:进阶篇下
这是记录前端面试的话术集锦第四篇博文——进阶篇下,我会不断更新该博文。❗❗❗ 1. 浏览器Eventloop和Node中的有什么区别 众所周知JS是⻔⾮阻塞单线程语⾔,因为在最初JS就是为了和浏览器交互⽽诞⽣的。 如果JS是⻔多线程的语⾔话,我们在多个线程中处理DOM就可能会发⽣问…...

mmap详解
想写一篇文章,详细的介绍一下mmap,主要是原理、用法、mmap泄露来进行介绍。说到mmap,首先得从堆空间说起。 申请堆空间 其实,不管是 32 位系统还是 64 位系统,内核都会维护一个变量 brk,指向堆的顶部&…...

项目02—基于keepalived+mysqlrouter+gtid半同步复制的MySQL集群
文章目录 一.项目介绍1.拓扑图2.详细介绍 二.前期准备1.项目环境2.IP划分 三. 项目步骤1.ansible部署软件环境1.1 安装ansible环境1.2 建立免密通道1.3 ansible批量部署软件1.4 统一5台mysql服务器的数据 2.配置基于GTID的半同步主从复制2.1 在master上安装配置半同步的插件,再…...

【EI征稿】第二届机械电子工程与人工智能国际学术会议(MEAI 2023)
第二届机械电子工程与人工智能国际学术会议(MEAI 2023) The 2nd International Conference on Mechatronic Engineering and Artificial Intelligence 2023年第二届机械电子工程与人工智能国际学术会议(MEAI 2023)计划将于2023年…...
ros2 学习launch文件组织工程 yaml配置文件
简单范例 功能描述 使用launch文件,统一管理工程,实现img转点云,发送到img_pt的topic,然后用reg_pcl节点进行subscribe,进行点云配准处理,输出融合后的点云到map_pt的topic。最后由rviz2进行点云展示。 …...

奇舞周刊第 505 期:实践指南-前端性能提升 270%!
记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ 实践指南-前端性能提升 270% 当我们疲于开发一个接一个的需求时,很容易忘记去关注网站的性能,到了某一个节点,猛地发现,随着越来越多…...

【C++】泛型编程 | 函数模板 | 类模板
一、泛型编程 泛型编程是啥? 编写一种一般化的、可通用的算法出来,是代码复用的一种手段。 类似写一个模板出来,不同的情况,我们都可以往这个模板上去套。 举个例子: void Swap(int& a, int& b) {int tmp …...

web前端——简单的网页布局案列
✨博主:命运之光 🌸专栏:Python星辰秘典 🐳专栏:web开发(简单好用又好看) ❤️专栏:Java经典程序设计 ☀️博主的其他文章:点击进入博主的主页 目录 问题背景 解决样例 …...

线程安全问题(3)--- wait(),notify()
前言 在多线程的环境下,我们常常要协调多个线程之间的执行顺序,而为了实现这一点,Java提供了一些方法来帮助我们完成这一点。 一,wait() 作用: 使当前线程进入等待状态 释放当前的锁 (即该方法必须和 synchrnized 关键…...
【Android知识笔记】进程通信(一)
一、Android Framework 用到了哪些 IPC 方式 Linux 的 IPC 方式有: 管道Socket共享内存信号信号量消息队列管道通信 管道是基于pipefs文件系统实现的,也就是多个进程通过对同一个文件进行读写来实现进程间通信。半双工,单向的,通过 pipe(fds) 系统函数调用可得到一对文件描…...

存储空间压缩6倍 ,多点DMALL零售SaaS场景降本实践
🧑💼 作者简介 冯光普:多点 DMALL 数据库团队负责人,负责数据库稳定性建设与 DB PaaS 平台建设,在多活数据库架构、数据同步方案等方面拥有丰富经验。 杨家鑫:多点高级 DBA,擅长故障分析与性能…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...

Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...

免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

STM32HAL库USART源代码解析及应用
STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...