数据结构之单链表

目录

1.链表的概念和结构

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

与顺序表不同,链表的每个节点都是独立申请下来的空间。

节点分成两个部分:当前节点保存的数据和保存的下一节点的地址(指针变量)

为什么我们需要指针变量来保存下一节点的位置?

链表中每一个节点都是单独申请的(需要插入数据就去申请一个节点),我们需要一个指针来保存下一个节点的地址,这样我们才能找到下一个节点。

c 复制代码
//用结构体定义节点的结构
typedef int SLTDataType;//对int重命名,可以提高代码的可维护性

struct Slist
{
	SLTDataType data;//节点中的数据
	struct Slist* next;//用指针变量保存下一个节点的地址
};

typedef struct Slist SLTNode;

提醒:

  • 链表在逻辑结构上是连续 的,在物理结构上不一定连续
  • 节点的空间一般是从堆上申请的

2.链表的分类

链表的结构有很多,但是平时我们用得最多的就是单链表 (单向,不带头,不循环)和双向循环链表 (双向,带头,循环)



  • 单向不带头不循环链表
    • 结构简单,一般不会单独用来存储数据。实际中更多的是作为其他数据结构的子结构
  • 双向带头循环链表
    • 结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是双向带头循环链表。

3.单链表(单向,不循环,不带头)的实现

3.1 开辟空间

c 复制代码
//向内存中申请空间
SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

每个节点开辟一般都是采用动态内存开辟,这里我选用的是malloc函数,因为开辟的是节点所以sizeof里面的LTNode,数据就直接插入,我们要让新开辟的节点的next指针指向NULL。最后我们要返回该节点的地址。

3.2 打印

给定了链表,我们应该怎样实现从头到尾的打印呢?

这里我创建了一个节点指针(头指针plist让它指向第一个节点,经过遍历,知道节点的next==NULL就停止

c 复制代码
//打印
void SLTPrint(SLTNode* phead)
{
	//phead!=NULL
	//因为不能对NULL进行解引用
	SLTNode* cur = phead;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

3.3尾插

c 复制代码
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);//pphead不能为空,不能对NULL进行解引用
	//先申请空间
	SLTNode* newnode = SLTBuyNode(x);

	//插入数据
	//if没有节点
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else//至少有1个节点
	{
		SLTNode* cur = *pphead;
		while (cur->next != NULL)
		{
			cur = cur->next;
		}
		cur->next = newnode;
	}
}

3.4 头插

c 复制代码
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);//pphead不能为空,不能对NULL进行解引用
	//申请空间
	SLTNode* newnode = SLTBuyNode(x);

	//插入数据
	newnode->next = *pphead;
	*pphead = newnode;
}

3.5 尾删

c 复制代码
//尾删
void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);//链表也不能为空
	//如果只有1个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else//至少有2个节点
	{
		SLTNode* cur = *pphead;
		SLTNode* prev = NULL;
		while (cur->next != NULL)
		{
			prev = cur;
			cur = cur->next;
		}
		prev->next = NULL;
		free(cur);
		cur = NULL;
	}
}

3.6 头删

c 复制代码
//头删
void SLTPopFront(SLTNode** pphead)
{
	assert(pphead && *pphead);//链表是空就不用删了

	//如果只有1个节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else//至少有2个节点
	{
		SLTNode* cur = *pphead;
		*pphead = cur->next;
		free(cur);
		cur = NULL;
	}
}

3.7 查找

c 复制代码
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	assert(phead);//链表为空就不用找了
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}

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

c 复制代码
//在指定位置之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pos);
	assert(pphead && *pphead);

	//在pos之前插入
	//如果pos在头节点,就采用头插
	if (pos == *pphead)
	{
		SLTPushFront(pphead, x);
	}
	else//pos不在头节点处
	{
		SLTNode* newnode = SLTBuyNode(x);
		SLTNode* cur = *pphead;
		while (cur->next != pos)
		{
			cur = cur->next;
		}
		//cur newnode pos
		cur->next = newnode;
		newnode->next = pos;
	}
}

3.9 删除指定位置的数据

c 复制代码
//删除指定节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pos);
	assert(pphead && *pphead);

	//如果pos的位置在头节点
	if (pos == *pphead)
	{
		SLTPopFront(pphead);
	}
	else//至少有2个节点
	{
		SLTNode* cur = *pphead;
		SLTNode* next = pos->next;

		while (cur->next != pos)
		{
			cur = cur->next;
		}
		cur->next = next;
		free(pos);
		pos = NULL;
	}
}

3.10 销毁链表

c 复制代码
//销毁
void SLTDestory(SLTNode** pphead)
{
	assert(pphead && *pphead);
	SLTNode* cur = *pphead;
	while (cur)
	{
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
}

链表的接口还有很多,这里我就写了一些比较常见的接口实现,后面的其他接口就不一 一写了

相关推荐
就爱学编程8 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
ALISHENGYA1 小时前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
波音彬要多做3 小时前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Noah_aa3 小时前
代码随想录算法训练营第五十六天 | 图 | 拓扑排序(BFS)
数据结构
KpLn_HJL4 小时前
leetcode - 2139. Minimum Moves to Reach Target Score
java·数据结构·leetcode
AC使者10 小时前
5820 丰富的周日生活
数据结构·算法
无 证明10 小时前
new 分配空间;引用
数据结构·c++
别NULL14 小时前
机试题——疯长的草
数据结构·c++·算法