手把手教你写一个单链表

目录

引言

单链表

数据节点

创建一个数据节点

打印链表

尾插数据

头插数据

尾删数据

头删数据

找数据

指定位置后插入数据

数指定位置后删数据

链表销毁


引言

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。像上一篇博客就是一个顺序表的构建。

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

单链表

数据节点

我们知道链表结构和顺序表不同,不是一块连续的空间,而是一个个的数据节点,所以我们先要规定一个数据节点是怎么样的,首先要包含想要储存的数据,然后是要包含指向下一个节点的指针,只有这样才能把一个个松散的节点串联在一起。

//确定数据节点中储存的数据类型
typedef int SListDateType;

//节点的结构
struct SListNode
{
	SListDateType val;
	struct SListNode* next;
};
typedef struct SListNode  SListNode;

创建一个数据节点

SListNode* BuySListNode(SListDateType x)
{
	SListNode* newnode = (SListNode*)malloc(sizeof(SListNode));
	assert(newnode);
	newnode->val = x;
	newnode->next = NULL;
}

这没什么好说的,就是根据数据节点结构开辟空间,对其初始化。

打印链表

void SListPrint(SListNode* head)
{
	SListNode* cur = head;
	while (cur != NULL)
	{
		printf("%d->", cur->val);
		cur = cur->next;
	}
	printf("NULL");
}

尾插数据

void SListPushBack(SListNode** pphead, SListDateType x)
{
	SListNode* newnode = BuySListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
	SListNode* cur = *pphead;
	while (cur->next != NULL)
	{
		cur = cur->next;
	}
	cur->next = newnode;
}

 特别要注意,这里传的是头节点的二级指针,因为可能要改变指针的值,我们知道在C语言中如果想要传值后改变相应的值,就要传相应的指针,因为想改变一级指针,就要传二级指针。

头插数据

void SListPushFront(SListNode** pphead, SListDateType x)
{
	SListNode* newnode = BuySListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

尾删数据

void SListPopBack(SListNode** pphead)
{
	assert(*pphead);
	SListNode* prev = NULL;
	SListNode* cur = *pphead;
	while (cur->next != NULL)
	{
		prev = cur;
		cur = cur->next;
	}
	free(cur);
	cur = NULL;
	if (prev == NULL)
	{
		*pphead = prev;
	}
	else
	{
		prev->next = NULL;
	}
}

头删数据

void SListPopFront(SListNode** pphead)
{
	assert(*pphead);
	SListNode* cur = *pphead;
	*pphead = cur->next;
	free(cur);
	cur = NULL;
}

找数据

SListNode* SListFind(SListNode* phead, SListDateType x)
{
	assert(phead);
	SListNode* cur = phead;
	while (cur != NULL)
	{
		if (cur->val == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return cur;
}

指定位置后插入数据

void SListInsertAfter(SListNode* pos, SListDateType x)
{
	assert(pos);
	SListNode* newnode = BuySListNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

数指定位置后删数据

void SListEraseAfter(SListNode* pos)
{
	assert(pos);
	assert(pos->next);
	SListNode* cur = pos->next;
	pos->next = cur->next;
	free(cur);
	cur = NULL;
}

链表销毁

void SListDestroy(SListNode* phead)
{
	assert(phead);
	SListNode* cur = phead;
	SListNode* back = phead->next;
	while (back != NULL)
	{
		free(cur);
		cur = back;
		back = back->next;
	}
	free(cur);
	cur = NULL;
}

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JDSZGLLL

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值