数据结构——单链表详解

博客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;
}
相关推荐
apocelipes3 小时前
Linux c 运行时获取动态库所在路径
linux·c语言·linux编程
int型码农4 小时前
数据结构第八章(一) 插入排序
c语言·数据结构·算法·排序算法·希尔排序
怀旧,5 小时前
【数据结构】6. 时间与空间复杂度
java·数据结构·算法
积极向上的向日葵5 小时前
有效的括号题解
数据结构·算法·
Java 技术轻分享6 小时前
《树数据结构解析:核心概念、类型特性、应用场景及选择策略》
数据结构·算法·二叉树··都差速
chao_7897 小时前
链表题解——两两交换链表中的节点【LeetCode】
数据结构·python·leetcode·链表
学习噢学个屁7 小时前
基于STM32语音识别柔光台灯
c语言·stm32·单片机·嵌入式硬件·语音识别
曦月逸霜7 小时前
第34次CCF-CSP认证真题解析(目标300分做法)
数据结构·c++·算法
吴声子夜歌10 小时前
OpenCV——Mat类及常用数据结构
数据结构·opencv·webpack
笑口常开xpr11 小时前
数 据 结 构 进 阶:哨 兵 位 的 头 结 点 如 何 简 化 链 表 操 作
数据结构·链表·哨兵位的头节点