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

探索双链表:C语言中的链式结构魔法

目录

引言

一、双链表基础

1.1、什么是双链表?

1.2、双链表节点的结构定义

二、双链表的基本操作

2.1、双链表的初始化

2.2、尾插法

2.3、头插

2.4、判断双链表是否为空

2.5、尾删法

2.6、头删法

2.7、查找

2.8、双链表在指定位置之前插入

2.9、双链表删除指定节点

2.10、双链表的销毁

三、总结

结语


引言

在程序设计中,数据结构扮演着至关重要的角色。链表作为一种基础且强大的数据结构,广泛应用于需要动态内存管理和高效插入删除的场景。而双链表作为链表的一种拓展,具有双向遍历的能力,为我们的算法设计提供了更大的灵活性。本篇博客将带你深入了解C语言中的双链表,包括其定义、基本操作以及实际应用,让你在掌握数据结构的同时,提高编程的效率与能力

一、双链表基础

1.1、什么是双链表?

双链表同单链表一样,是一种线性结构的数据结构,与单链表不同的是,双链表的每个节点有两个指针,分别指向下一个节点和上一个节点。这使得双链表既可以向前遍历,也可以向后遍历,极大的节省了时间,但代价就是每个节点所占用的空间变大了。

1.2、双链表节点的结构定义

typedef int DLElemType;
typedef struct DListNode
{DLElemType data;   //节点的数据域struct DListNode* next;   //指向下一个节点struct DListNode* prev;   //指向上一个节点
}DListNode;

二、双链表的基本操作

2.1、双链表的初始化

void DLInit(DListNode** pphead)
{*pphead = (DListNode*)malloc(sizeof(DListNode));if (*pphead == NULL){perror("malloc fail!");exit(1);}(*pphead)->data = 0;(*pphead)->next = (*pphead)->prev = *pphead;
}

这里要注意的是,为了与其他类型的链表区分,双链表的初始化让两个指针都指向自己

2.2、尾插法

void DLPushBack(DListNode* phead , DLElemType x)
{assert(phead);DListNode* newnode = (DListNode*)malloc(sizeof(DListNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = phead;newnode->prev = phead->prev;phead->prev->next = newnode;phead->prev = newnode;
}

在单链表中,我们要进行尾差就必须遍历找到最后一个节点,但是在双链表中,我们只需要找到头结点的prev指向就可以了,非常的方便

2.3、头插

在此之前,我们需要编写一个函数来实现新节点的创建,一次来提高效率:

//创建一个新的双链表节点
DListNode* BuyDListNode(DLElemType x)
{DListNode* newnode = (DListNode*)malloc(sizeof(DListNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = newnode->prev = NULL;return newnode;
}

接下来就是头插法的实现了

//头插
void DLTPushFront(DListNode* phead, DLElemType x)
{assert(phead);DListNode* newnode = BuyDListNode(x);newnode->prev = phead;newnode->next = phead->next;phead->next->prev = newnode;phead->next = newnode;
}

2.4、判断双链表是否为空

//判断双链表是否为空
bool DLTEmpty(DListNode* phead)
{assert(phead);return phead->next == phead;
}

2.5、尾删法

void DLTPopBack(DListNode* phead)
{assert(phead && !DLTEmpty(phead));DListNode* pcur = phead->prev;pcur->prev->next = phead;phead->prev = pcur->prev;free(pcur);pcur = NULL;
}

2.6、头删法

void DLTPopFront(DListNode* phead)
{assert(phead && !DLTEmpty(phead));DListNode* pcur = phead->next;phead->next = pcur->next;pcur->next->prev = phead;free(pcur);pcur = NULL;
}

2.7、查找

DListNode* DLTFind(DListNode* phead, DLElemType x)
{assert(phead && !DLTEmpty(phead));DListNode* pcur = phead->next;while (pcur != phead){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}

2.8、双链表在指定位置之前插入

void DLTInsert(DListNode* pos, DLElemType x)
{assert(pos);DListNode* newnode = BuyDListNode(x);newnode->next = pos;newnode->prev = pos->prev;pos->prev->next = newnode;pos->prev = newnode;
}

2.9、双链表删除指定节点

void DLTErase(DListNode* pos)
{assert(pos);pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);pos = NULL;
}

2.10、双链表的销毁

void DLTDestory(DListNode** pphead)
{assert(pphead && *pphead);DListNode* pcur = (*pphead)->next;while (pcur != *pphead){DListNode* tmd = pcur->next;free(pcur);pcur = tmd;}free(*pphead);*pphead = NULL;
}

三、总结

掌握了单链表,那么掌握双链表也是分分钟的事,本篇以有哨兵位,循环的双链表为目的编写的代码。双链表的实际应用广泛,例如播放器的歌曲上一首下一首 ,以及网页的进一步退一步等。双链表非常好掌握,这里就不多赘述了

结语

通过对双链表的系统讲解与实践操作,相信你已经对其核心思想与实现细节有了更深的理解。双链表不仅是数据存储的利器,更是算法设计中不可或缺的基础结构。在今后的学习与开发中,灵活运用双链表,将会让你的代码更加高效、优雅。希望这篇文章能为你打开链式结构世界的大门,助你在编程之路上越走越远!

http://www.lryc.cn/news/598866.html

相关文章:

  • matplotlib的详细知识点
  • AUTOSAR进阶图解==>AUTOSAR_SWS_BSWModeManager
  • ANSYS Fluent 管内流动仿真
  • MySQL 8.0 OCP 1Z0-908 题目解析(35)
  • 字符串和对象的深拷贝和浅拷贝
  • 电商接口常见误区与踩坑提醒
  • Spring Cloud Alibaba Sentinel 源码阅读之流量控制算法
  • PCL 间接平差拟合球
  • Spring MVC 统一响应格式:ResponseBodyAdvice 从浅入深
  • 论文阅读:《针对多目标优化和应用的 NSGA-II 综述》一些关于优化算法的简介
  • 7.24 C/C++蓝桥杯 | 排序算法
  • 面试题(技术面+hr面)
  • Sklearn 机器学习 数值标准化
  • C++高效实现轨迹规划、自动泊车、RTS游戏、战术迂回包抄、空中轨迹、手术机器人、KD树
  • JSONObject相关知识点
  • 【MediaTek】AN7563编译出现npu/en7563/host/Makefile: No such file or directory
  • Silly Tavern 教程②:首次启动与基础设置
  • Windows 如何更改 ModelScope 的模型下载缓存位置?
  • 循环神经网络--LSTM模型
  • 跨境支付入门~国际支付结算(区块链篇)
  • 推荐系统如何开发
  • AI大模型资源
  • Spring Boot 遇上 MyBatis-Plus:高效开发的奇妙之旅
  • 10_Spring Boot 中的 @Scheduled 注解是单线程还是多线程?同步还是异步?
  • Percona pt-archiver 出现长事务
  • IntelliJ IDEA
  • 单片机的第一个程序—LED灯的控制
  • HBase + PostgreSQL + ElasticSearch 联合查询方案
  • 斐波那契数列策略
  • 新能源电池厂自动化应用:Modbus TCP转DeviceNet实践