数据结构——单链表详解

博客IDLanFuRen
C系列专栏 C语言重点部分 C语言注意点 C++基础 Linux 数据结构 C++注意点

声明等级:黑色->蓝色->红色

欢迎新粉加入,会一直努力提供更优质的编程博客,希望大家三连支持一下啦

目录

1.链表的概念

2.单链表主体的实现

3.单链表内部方法实现

1)二级指针的问题

2)头插尾插的实现

3)其他代码展示


1.链表的概念

链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。

链表就像火车一样,由一节一节车厢所构成。

从概念图可以看出,下一节"车厢",通过上一节"车厢"中的指针来链接。由上图,我们可以清晰地写出链表的主体部分,该链表结构体中有两个结构体成员------节点所存入的数据,结构体指针存放下一个节点的地址。(车厢=节点)。

2.单链表主体的实现

代码如下:

cpp 复制代码
typedef struct SListNode
{
	int data;//存放的数据
	struct SListNode* next;//结构体指针
}SLTNode;

SList:single单个的意思,list代表链表,node代表节点。

3.单链表内部方法实现

这里依旧提供几个比较重要的方法的实现过程:

//链表的打印

void SLTPrint(SLTNode* phead);

//链表的头插、尾插

void SLTPushBack(SLTNode** pphead, SLTDataType x);

void SLTPushFront(SLTNode** pphead, SLTDataType x);

链表的头删、尾删

void SLTPopBack(SLTNode** pphead);

void SLTPopFront(SLTNode** pphead);

//查找

SLTNode* SLTFind(SLTNode** pphead, SLTDataType x);

//在指定位置之前插入数据

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);

//在指定位置之后插入数据

void SLTInsertAfter(SLTNode* pos, SLTDataType x);

//删除pos节点

void SLTErase(SLTNode** pphead, SLTNode* pos);

1)二级指针的问题

我们先来看看这里的二级指针的问题,为什么要使用SLTNode**pphead?那我们就得看实参跟形参的关系了,我们实参应该是一个链表,假设名字是plist,**我们要在函数中去修改这个plist,即修改plist存放的地址(指向),**而这个plist应该是SLTNode*plist=NULL(节点),**我们要去修改一级指针的值,就需要得到一级指针的地址,**这样就用到了二级指针。

2)头插尾插的实现

代码如下:

cpp 复制代码
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	/*if (*pphead==NULL)
	{
		*pphead = newnode;
		return;
	}*/
	newnode->next = *pphead;
	*pphead = newnode;//重要
}
cpp 复制代码
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)//传二级指针是因为这样才能修改plist链表,我们想获得plist的内部成员(节点内容),就是值,得传址,所以说传二级指针
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	//空链表
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
	//链表不为空
	SLTNode* ptail = *pphead;//ptail是一级指针
	while (ptail->next)
	{
		ptail = ptail->next;//ptail指针存放的是节点地址,节点包括next,这一步仅仅传一级指针就行。
	}
	ptail->next = newnode;

	/*while ((*pphead)->next)
	{
		*pphead = (*pphead)->next;
	}
	(*pphead)->next = newnode;*/
}

3)其他代码展示

cpp 复制代码
//尾删
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		(*pphead)=NULL;
		return;
	}
	SLTNode* prev = *pphead;
	SLTNode* ptail = *pphead;
	while (ptail->next)
	{
		prev = ptail;//上一级
		ptail = ptail->next;//尾
	}
	prev->next = NULL;
	free(ptail);
	ptail = NULL;
}

void SLTPopFront(SLTNode** pphead) 
{
	assert(pphead);
	assert(*pphead);
	SLTNode* del = *pphead;
	*pphead= (*pphead)->next ;
	free(del);
	del = NULL;
	/*SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;*/
}

//查找
//为指定位置增删有帮助
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	//assert(*pphead);
	SLTNode* val = *pphead;
	while (val != NULL)
	{
		if (val->data == x)
		{
			return val;
		}
		val = val->next;
	}
	return NULL;
}

在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);//空链表哪里来的指定位置插入
	SLTNode* newnode = SLTBuyNode(x);
	if (pos == *pphead)
	{
		SLTPushFront(pphead, x);
		return;
	}//头节点
	//不是头节点
	SLTNode* pos_before = *pphead;
	while (pos_before->next != pos)
	{
		pos_before = pos_before->next;
	}
	/*pos_before->next = newnode->data;
	newnode->next = pos->data;*/
	pos_before->next = newnode;
	newnode->next = pos;
}

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos) 
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	//pos刚好是头结点,没有前驱节点,执行头删
	if (*pphead == pos) {
		//头删
		SLTPopFront(pphead);
		return;
	}
	SLTNode* pos_before = *pphead;
	while (pos_before->next != pos)
	{
		pos_before = pos_before->next;
	}//找到前驱节点
	SLTNode* pos_after = pos->next;//后驱节点
	pos_before->next = pos_after;
	//pos->next = NULL;
	free(pos);
	pos = NULL;
}
相关推荐
何其有幸.2 小时前
实验6-3 使用函数求特殊a串数列和(PTA|C语言)
c语言·数据结构·算法
不会计算机的捞地2 小时前
【数据结构入门训练DAY-24】美国大选
数据结构·算法
.似水2 小时前
2025.4.22_C_可变参数列表
java·c语言·算法
Felven3 小时前
A. Ideal Generator
java·数据结构·算法
How_doyou_do3 小时前
树状数组底层逻辑探讨 / 模版代码-P3374-P3368
数据结构·算法·树状数组
小鹿鹿啊4 小时前
C语言编程--14.电话号码的字母组合
c语言·开发语言·算法
一只鱼^_4 小时前
第十六届蓝桥杯大赛软件赛省赛 C/C++ 大学B组 [京津冀]
c语言·数据结构·c++·算法·贪心算法·蓝桥杯·动态规划
Kisorge5 小时前
【电机仿真】MPC模型预测转速、电流双闭环控制器——PMSM有感FOC控制
c语言
云格~5 小时前
Leetcode:1. 两数之和
数据结构·算法·leetcode
几点才到啊5 小时前
C语言实现冒泡排序:算法原理与代码解析
c语言·算法·排序算法