【C语言数据结构】之解锁双向链表(指定位置插入、删除节点、查找、销毁链表等操作)

"Hello大家好,欢迎来到**【01二进制代码漫游日记】!**

今天我们的主题是C语言数据结构中的双向链表。我们将快速解锁它的核心操作:指定位置插入、删除节点、查找以及销毁链表。话不多说,直接上代码,一起玩转双向链表!"

"在正式动手写代码之前,我们先来认识一下今天项目的'三剑客'。一个结构清晰的项目,能让我们的思路事半功倍。我们一共准备了三个文件,它们各司其职,协同工作。"

一、文件定义及作用

1.1.List.h文件及作用

首先登场的是我们的'总设计师'------List.h头文件。它的作用非常关键,负责定义双向链表的'蓝图',也就是我们的节点结构体,同时也会声明所有函数的接口。其他文件想要和链表打交道,都得先包含它。

1.2.4-21.c文件及作用

接下来是我们的'实干家'------4-21.c实现文件。所有函数的具体逻辑和'硬功夫',比如插入、删除节点的具体代码,都会写在这里。它是整个项目的核心。

1.3.test.h文件及作用

最后是我们的'体验官'------test.h测试文件。它是程序的入口,也就是main函数所在的地方。我们会在这里演示如何使用前面定义好的所有功能,来验证我们的链表是否工作正常。

好了,认识了这三位'伙伴',"项目结构清晰了,万事俱备,只欠代码!那我们该从哪里下手呢?对于一个数据结构来说,'查找'是所有操作的基石。只有先学会了如何精准定位,我们才能对它进行后续的增删改。所以,我们的第一站,就从这里开始。

二、查找及其实现方法

2.1.List.h部分

代码如下:

#pragma once

#include<stdio.h>

#include<stdlib.h>

#include<assert.h>

typedef int LTDataType;

typedef struct LTNode {

LTDataType data;

struct LTNode* prev;

struct LTNode* next;

}LTNode;

//申请节点

LTNode* LTBuyNode(LTDataType x);

void LTInit(LTNode** pphead);

void LTPushBack(LTNode* phead, LTDataType x);

void LTPrint(LTNode* phead);

void LTPushFront(LTNode* phead, LTDataType x);

void LTPopBack(LTNode* phead);

//头删

void LTPopFront(LTNode* phead);

//查找

LTNode* LTFind(LTNode* phead, LTDataType x);

2.2.4-21.c部分

查找代码如下:

//查找

LTNode* LTFind(LTNode* phead, LTDataType x) {

assert(phead);

LTNode* pcur = phead->next;

while (pcur != phead) {

if (pcur->data == x) {

return pcur;

}

pcur = pcur->next;

}

return NULL;

}

2.3.test.c部分

测试代码如下:

//查找

LTNode*pos=LTFind(plist, 1);

if (pos != NULL) {

printf("找到了,是%d\n",pos->data);

}

else {

printf("没有找到,请重新输入:");

}

}

测试结果如下:

"查找是为了定位,而定位往往是为了后续的修改做准备。搞定了'在哪里'的问题,接下来我们看看'怎么做'------如何在找到的这个位置之后,插入新的节点

三、在指定位置之后插入数据

3.1.List.h部分

代码如下:

//在指定位置之后插入新结点

void LTInsert(LTNode* phead, LTDataType x);

3.2.4-21.c部分

代码如下:

//在指定位置之后插入新结点

void LTInsert(LTNode* pos, LTDataType x) {

assert(pos);

LTNode* newnode = LTBuyNode(x);

newnode->next = pos->next;

newnode->prev = pos;

pos->next->prev = newnode;

pos->next = newnode;

}

3.3.test.c部分

代码如下:

//在指定位置之后插入新结点

LTNode* pos2 = LTFind(plist, 2);

if (pos2) {

LTInsert(pos2, 8);

}

LTNode* pos4 = LTFind(plist, 9);

if (pos4) {

LTInsert(pos4, 9);

}

LTPrint(plist);

测试结果如下:

"在动态的数据世界里,有增就有减。我们刚刚攻克了'在指定位置之后插入数据'的难题,让链表变得灵活多变。但光会'增'还不够,当某个节点的数据过时或无效时,我们需要一种机制来'修剪'它。接下来,我们就来探讨如何删除指定位置的节点。"

四、删除pos(指定位置)节点

4.1.List.h部分

代码如下:

#pragma once

#include<stdio.h>

#include<stdlib.h>

#include<assert.h>

typedef int LTDataType;

typedef struct LTNode {

LTDataType data;

struct LTNode* prev;

struct LTNode* next;

}LTNode;

//申请节点

LTNode* LTBuyNode(LTDataType x);

void LTInit(LTNode** pphead);

void LTPushBack(LTNode* phead, LTDataType x);

void LTPrint(LTNode* phead);

void LTPushFront(LTNode* phead, LTDataType x);

void LTPopBack(LTNode* phead);

//头删

void LTPopFront(LTNode* phead);

//查找

LTNode* LTFind(LTNode* phead, LTDataType x);

//在指定位置之后插入新结点

void LTInsert(LTNode* pos, LTDataType x);
//删除指定位置结点
void LTErase(LTNode* pos);

4.2. 4-21.c部分

代码如下:

//删除指定位置结点

void LTErase(LTNode* pos) {

assert(pos);

pos->next->prev = pos->prev;

pos->prev->next = pos->next; \

free(pos);

pos = NULL;

}

4.3.test.c部分

代码如下:

//删除指定位置结点

LTNode* pos = LTFind(plist, 9);

if (pos != NULL) {

LTErase(pos);

}

LTPrint(plist);

测试结果如下:

"我们刚刚学会了如何精准地删除单个节点,就像处理掉一个废弃的零件。但在程序的世界里,当我们彻底完成一个任务,不再需要整个数据结构时,就不能只删除某一个节点了。我们需要一种'大扫除'式的操作,一次性释放所有节点,将内存归还给系统。这不仅是一种操作,更是一种编程的责任。下面,让我们来完成链表的销毁。"

五、销毁链表

5.1List.h部分

代码如下:

//销毁链表

void LTDestroy(LTNode* phead);

5.2. 4-21.c部分

代码如下:

//销毁链表

void LTDestroy(LTNode* phead) {

assert(phead);

LTNode* pcur = phead->next;

while (pcur != phead) {

LTNode* next = pcur->next;

free(pcur);

pcur = next;

}

free(phead);

phead = NULL;

}

5.3.test.c部分

代码如下:

LTPrint(plist);

//销毁链表

LTDestroy(plist);

LTPrint(plist);

plist = NULL;

}

"OK,双向链表的关键操作就介绍到这里。希望大家通过今天的学习,能轻松掌握它!

如果觉得有用**,别忘了关注我,**获取更多编程技巧和实战经验。你的支持是我更新的动力!我们下期见!"

相关推荐
刘马想放假21 小时前
Modbus 全栈技术解析:TCP、RTU、ASCII、RTU over TCP
数据结构·网络协议
北域码匠2 天前
冒泡排序太慢?鸡尾酒排序双向优化,原生 C# 零第三方库完整代码
数据结构·排序算法·泛型·c# 算法·鸡尾酒排序·原生 c# 开发·冒泡排序优化·嵌入式算法
Darling噜啦啦9 天前
列表转树算法深度解析:从 Map 到 Reduce 的两种实现,面试高频考点
数据结构·算法·面试
LDR00610 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
小小工匠10 天前
Redis - 事务机制:能实现 ACID 属性吗
数据结构·redis·性能优化·并发·持久化
Luminous.10 天前
C语言--day30
c语言·开发语言
玖玥拾10 天前
C/C++ 数据结构(七)栈、容器适配器
c语言·数据结构·c++··容器适配器
謓泽10 天前
C语言不是语法,是通往机器的地图。
c语言·开发语言
不会C语言的男孩10 天前
Linux 系统编程 · 第 8 章:进程基础
linux·c语言
Qres82110 天前
算法复键——树状数组
数据结构·算法