单链表的实现

本文详细介绍了链表的概念,包括链表的逻辑结构和物理存储特性,并提供了链表的基本操作实现,如节点创建、插入、删除以及节点查找等,最后展示了如何销毁链表节点。
摘要由CSDN通过智能技术生成

一、链表的概念

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

二、链表的基本实现

1、初始化`

其中SL是链表的缩写

typedef int SLTDateType;
typedef  struct SListNode
{
	SLTDateType Date;
	SListNode* next;
}SListNode;

2、节点的创建 SLTBuyNode

此处节点的创建为了接下来的增加节点铺垫

SLTNode*SLTBuyNode(SLTDataType x)//创建一个新的节点,节点后接空指针
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;

	return newnode;

}

3、节点打印SLTPrint

方便后面的调试,
1,同时这里只是传一级指针因为单链表是连续的可以直接找到并打印,
2,下面会传二级指针因为下面会修改链表,高一级指针才可以将修改后的值传回去

void SLTPrint(SLTNode* phead) {
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}

4、头插SLTPushFront

1,创造一个节点newNode
2,把新节点下一位接到原节点*pphead开头
3、将开头节点提前到newNode

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = *pphead;//将空指针介入
	*pphead = newnode;//定义头指针
}

5、尾插SLTPushBack

两种情况
1、插空
2、非空,其中ptail是找尾节点的,有一个易错点,必须将头节点赋给一个节点ptail,来遍历,不然的话直接用头结点,头结点会不断覆盖

void SLTPushBack(SLTNode**pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode*newnode=SLTBuyNode(x);
	//链表为空
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;

	}
	//链表不为空
	SLTNode* ptail = *pphead;//易错点
	while (ptail->next)
	{
		ptail = ptail->next;//依次交换
	}
	ptail->next = newnode;//插入尾指针

}

6、头删SLTPopFront

void SLTPopFront(SLTNode** pphead)
{
	assert(pphead);
	SLTNode* ptail = *pphead;
	*pphead = (*pphead)->next;//把头节点赋给第二个节点
	free(ptail);
	ptail = NULL;
}

7、尾插SLTPopBack

分为两种情况
1.只有一个节点
2,大于两个节点,只有一点找不到倒数第二个节点,所以有prev=ptail,来找到现在最后一个节点

void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	SLTNode* ptail = *pphead;
	SLTNode* prev = NULL;
	while (ptail->next)
	{
		prev = ptail;
		ptail = ptail->next;
	}
	prev->next = NULL;
	free(ptail);
	ptail = NULL;
}

8、找节点SLTFind

SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* pcur = *pphead;
	while (pcur->next)
	{

		if (pcur->data == x)
		{
			return pcur;
		}
		pcur = pcur->next;
	}
	return NULL;
}

9、插pos前面SLTInsert

头插
下面是一个错误示范
目的是理解其中二级指针,一级指针的含义,这么写是错的,SLTPushBack里得参数
是二级指针,二级指针才能改变一级指针,但prev是一级指针
一级指针
SLTNode* prev = *pphead;
if (prev == pos)
{
SLTPushFront(&prev, x);
return;

}
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);//节点存在
	assert(*pphead);
	SLTNode* newnode = SLTBuyNode(x);
	
	//下面是修改
	if (*pphead == pos)
	{
		SLTPushFront(pphead, x);
		return;
	}
	SLTNode* prev = *pphead;
	while (prev->next!= pos)
	{
		prev = prev->next;
	}	prev->next = newnode;
	newnode->next = pos;
}

10、插pos后面SLTInsertAfter

void SLTInsertAfter(SLTNode* pphead, SLTNode* pos, SLTDataType x)
{
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
	//易错下面是错误写法
	// pos->next=newnode;
	//newnode->pos->next;
}

销毁节点11.SLTDesNode

void SLTDestroy(SLTNode**pphead)
{
	assert(pphead);
	assert(*pphead);
	SLTNode* pcur = *pphead;
	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	*pphead = NULL;
}

创作不易,希望点赞

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值