如何用C语言写双向链表
创作时间:
作者:
@小白创作中心
如何用C语言写双向链表
引用
1
来源
1.
https://docs.pingcode.com/baike/1019828
使用C语言实现双向链表
在C语言中,双向链表是一种灵活的数据结构,适用于需要频繁插入和删除操作的场景。双向链表的节点既包含指向下一个节点的指针,也包含指向前一个节点的指针、链表的操作包括节点的插入、删除、遍历等。以下将详细介绍如何用C语言实现双向链表,并提供代码示例和实践经验。
一、双向链表的基本结构
双向链表的基本结构包括节点和链表本身。每个节点包含三个主要部分:数据、指向下一个节点的指针和指向前一个节点的指针。
// 定义节点结构
typedef struct Node {
int data; // 数据部分
struct Node* next; // 指向下一个节点的指针
struct Node* prev; // 指向前一个节点的指针
} Node;
// 定义双向链表结构
typedef struct {
Node* head; // 指向链表的头节点
Node* tail; // 指向链表的尾节点
} DoublyLinkedList;
二、初始化双向链表
初始化双向链表时,需要将链表的头节点和尾节点指针设置为NULL。
// 初始化双向链表
void initList(DoublyLinkedList* list) {
list->head = NULL;
list->tail = NULL;
}
三、插入节点
在双向链表中插入节点可以在头部、尾部或指定位置插入。这里以头部和尾部插入为例。
1、头部插入节点
头部插入节点时,需要更新新节点的next指针和现有头节点的prev指针。
// 头部插入节点
void insertAtHead(DoublyLinkedList* list, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = list->head;
newNode->prev = NULL;
if (list->head != NULL) {
list->head->prev = newNode;
} else {
list->tail = newNode;
}
list->head = newNode;
}
2、尾部插入节点
尾部插入节点时,需要更新新节点的prev指针和现有尾节点的next指针。
// 尾部插入节点
void insertAtTail(DoublyLinkedList* list, int data) {
Node* newNode = (Node*)malloc(sizeof(Node));
newNode->data = data;
newNode->next = NULL;
newNode->prev = list->tail;
if (list->tail != NULL) {
list->tail->next = newNode;
} else {
list->head = newNode;
}
list->tail = newNode;
}
四、删除节点
在双向链表中删除节点时,需要考虑更新前后节点的指针。
1、删除头节点
删除头节点时,需要更新新头节点的prev指针。
// 删除头节点
void deleteAtHead(DoublyLinkedList* list) {
if (list->head == NULL) {
return;
}
Node* temp = list->head;
list->head = list->head->next;
if (list->head != NULL) {
list->head->prev = NULL;
} else {
list->tail = NULL;
}
free(temp);
}
2、删除尾节点
删除尾节点时,需要更新新尾节点的next指针。
// 删除尾节点
void deleteAtTail(DoublyLinkedList* list) {
if (list->tail == NULL) {
return;
}
Node* temp = list->tail;
list->tail = list->tail->prev;
if (list->tail != NULL) {
list->tail->next = NULL;
} else {
list->head = NULL;
}
free(temp);
}
五、遍历双向链表
遍历双向链表可以从头到尾或从尾到头遍历。
1、从头到尾遍历
// 从头到尾遍历
void traverseFromHead(DoublyLinkedList* list) {
Node* current = list->head;
while (current != NULL) {
printf("%d ", current->data);
current = current->next;
}
printf("n");
}
2、从尾到头遍历
// 从尾到头遍历
void traverseFromTail(DoublyLinkedList* list) {
Node* current = list->tail;
while (current != NULL) {
printf("%d ", current->data);
current = current->prev;
}
printf("n");
}
六、总结
通过上述代码示例,我们实现了双向链表的基本操作,包括初始化、插入节点、删除节点和遍历。双向链表相比单向链表的优势在于可以双向遍历和更高效地进行插入和删除操作,特别是在需要频繁操作的场景中,如实现LRU缓存、处理文本编辑器的撤销和重做操作等。
在实际应用中,我们可以根据具体需求扩展双向链表的功能,如在指定位置插入和删除节点、查找节点、逆序链表等。同时,在进行内存操作时,要注意防止内存泄漏,确保每个分配的节点都能被正确释放。
热门推荐
“魑魅魍魉”到底是指什么?其实许多人都是他们的后代
充电时 到底先插手机还是充电器?
Windows 10安全中心一直获取保护信息?八大解决方案帮你轻松应对
情绪的智慧之旅:青春期孩子的情绪管理与心理健康
55岁男子患上肝癌,每天喝蒲公英水,1年后复诊,医生:太无知
做校长,首先要管好团队的“精气神”
苹果型身材怎么穿更显瘦?上衣的选款和搭配技巧,看这一篇就够了
家庭吵架总升级,三招让沟通变轻松—用"冰箱对话法"让吵架变谈心
卤牛肉的“克星”香料:千里香、山楂和草果的作用与制作技巧
糖友早餐吃什么,更容易控糖?很多朋友都吃错了......
曲靖科技创新能力持续增强 支撑全市经济社会高质量发展
私营企业组织改革新思路,如何提升员工的参与度?
R语言数据探索与分析:中国GDP回归分析与预测
美国那点事|“超级星期二”之后,逐鹿2028的序幕已拉开
任天堂DS时代的结束对掌机游戏意味几何
年后穿搭指南:短靴中筒靴搭配技巧,轻松提升气质
【游戏设计原理】零和博弈在游戏设计中的应用
功能点估算方法(FP)详解
【拉沃尔杯】欧洲队惊天逆转世界队,七年之内五度加冕
高考志愿填报如何避免被高校调剂到不喜欢的专业中去?
人造石墨VS天然石墨:负极材料争霸战
哲学家的死亡观——苏格拉底论死亡
硫的奥秘!看它是如何影响世界的
勇气与美德:探索内心软弱的真谛
“古希腊三贤”之一:苏格拉底为何而死?他的死亡原因是什么?
《心经》中的“五蕴”:佛教对世界本质的独特理解
带着脑子去打乒乓球,业余爱好者在实战中应该具备的战术统计能力
老年人节日礼物指南:送父母健康礼品更贴心
大学生买电脑必看:六大关键配置点帮你选对笔记本
“识季”被指强买强卖:出售高价瑕疵品高跟鞋 与客服多次沟通无果