数据结构—单链表

单链表在物理空间上非线性的,相对于顺序表更加节省空间。

链表由一个一个的节点组成,每一个节点储存着数据和指向下一节点的指针,所以链表在逻辑上是线性的。

单链表的打印

cpp 复制代码
void SLTPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf(" %d ->", pcur->data);
		pcur = pcur->next;
	}
	printf(" NULL");
}

这里由于不需要对结构体进行修改所以传递一级指针

在单链表中插入数据

设置结点

cpp 复制代码
SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode SList;
	SLTNode* tmp = (SLTNode*)malloc(sizeof(SList));
	if (tmp == NULL)
	{
		perror("SLTBuyNode");
		exit(1);
	}
	tmp->data = x;
	tmp->next = NULL;
	return tmp;
}

在单链表尾部插入数据

cpp 复制代码
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* tmp = SLTBuyNode(x);
	if (*pphead == NULL)
	{
		*pphead = tmp;
	}
	else
	{
		SLTNode* ptr = *pphead;
		while (ptr->next)
		{
			ptr = ptr->next;
		}
		ptr->next = tmp;
	}
}

在单链表头部插入数据

cpp 复制代码
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* tmp = SLTBuyNode(x);
	tmp->next = *pphead;
	*pphead = tmp;
}

在单链表指定位置之前插入数据

cpp 复制代码
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead && *pphead&&pos);
	SLTNode* tmp = SLTBuyNode(x);
	if (*pphead == pos)
	{
		SLTPushFront(pphead, x);
	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev -> next;
		}
		prev->next = tmp;
		tmp->next = pos;
	}
}

在单链表指定位置之后插入数据

cpp 复制代码
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);
	SLTNode* tmp1 = pos->next;
	SLTNode* tmp2 = SLTBuyNode(x);
	pos->next = tmp2;
	tmp2->next = tmp1;
}

删除单链表的数据

删除单链表尾部的数据

cpp 复制代码
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		SLTNode* prev = *pphead;
		SLTNode* ptr = *pphead;
		while (ptr->next)
		{
			prev = ptr;
			ptr = ptr->next;
		}
		free(ptr);
		ptr = NULL;
		prev->next = NULL;
	}
}

删除单链表头部的数据

cpp 复制代码
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead&&*pphead);
	SLTNode* tmp = NULL;
	tmp = (*pphead)->next;
	free(*pphead);
	*pphead = tmp;
}

删除单链表指定位置的数据

cpp 复制代码
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead && *pphead&&pos);
	if (pos==*pphead)
	{
		SLTPopFront(pphead);
	}
	else
	{
		SLTNode* tmp = *pphead;
		while (tmp->next != pos)
		{
			tmp = tmp->next;
		}
		tmp->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

删除单链表指定位置之后的数据

cpp 复制代码
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos && pos->next);
	SLTNode* tmp = pos->next;
	pos->next = tmp->next;
	free(tmp);
	tmp = NULL;
}

查找单链表中的数据

cpp 复制代码
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	assert(phead);
	SLTNode* ptr = phead;
	while (ptr)
	{
		if (ptr->data == x)
			return ptr;
		else
			ptr = ptr->next;
	}
	return NULL;
}

单链表的销毁

cpp 复制代码
void SListDestroy(SLTNode** pphead)
{
	assert(pphead && *pphead);
	SLTNode* ptr = *pphead;
	SLTNode* tmp = *pphead;
	while (ptr)
	{
		tmp = ptr->next;
		free(ptr);
		ptr = tmp;
	}
	*pphead = NULL;
}

链表的分类

链表的结构非常多样,以下情况总结起来就有八种链表结构

带头

链表中有哨兵位节点,该哨兵位节点就是头节点。上文实现的链表中phead不表示头节点,表示第一个有效的节点。

单向/双向

循环/不循环

前面实现的链表就是不带头不循环 的单向链表,简称单链表

还有一个经常使用的链表就是带头循环 双向链表,简称双向链表

相关推荐
寂静山林几秒前
UVa 1597 Searching the Web
数据结构·算法
yong158585534322 分钟前
1. Linux C++ muduo 库学习——库的编译安装
linux·c++·学习
9523637 分钟前
数据结构-顺序表
java·数据结构·学习
码界奇点1 小时前
Java Web学习 第1篇前端基石HTML 入门与核心概念解析
java·前端·学习·xhtml
hazy1k2 小时前
51单片机基础-TFT LCD 显示(ILI9341,SPI 4线)
c语言·stm32·单片机·嵌入式硬件·51单片机
haofafa2 小时前
高精度加减法
java·数据结构·算法
星辰大海14122 小时前
摄影入门学习笔记
笔记·数码相机·学习
沐矢羽2 小时前
upload文件上传漏洞浅析
学习·web安全·网络安全·文件上传·top10
奔跑吧邓邓子2 小时前
【C语言实战(63)】从0到1:51单片机GPIO控制实战秘籍
c语言·51单片机·开发实战·gpio控制实战
shenghaide_jiahu2 小时前
数学分析简明教程——2.3 (未完)
学习