数据结构笔记--单链表(1)

一:定义链表

数据+指向下一个节点的指针

typedef int SLTDataType;
typedef struct SlistNode

{
    int data;
    struct SlistNode* next ;
}SLTNode;

上图即为一个简单的单链表。

下面初始化一个单链表:

1.1单链表的头插尾插

要做到头插/尾插,首先需要实现创建新节点

SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
			exit(1);
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

以上代码使用malloc函数,针对SLTNode的大小,给节点指针newnode分配空间,并将其存放的数据设置为x

1.1.1 头插实现

上传链表指向头节点(phead)的指针(pphead),使用BuyNode函数新建一个节点newnode,使其next指针指向原来的头节点phead

再将当前的newnode节点设置为头节点即可

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLTBuyNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

1.1.2尾插实现

尾插的思路是遍历链表,找到链表最后一个节点

当某个节点的next指针指向空,即node->next==NULL,则代表该节点没有可指向的节点,即为尾节点

代码中的思路是从头节点开始,假设其就是尾节点,以“其next指针是否指向空”为循环条件遍历整个链表

如果链表为空,直接使用BuyNode函数新建一个节点newnode,将其设置为头节点即可。

void SLTPushBack(SLTNode** pphead,SLTDataType x)
{
	SLTNode *newmode = SLTBuyNode(x);
	if (*pphead == NULL)//空链表尾插
	{
		*pphead = newmode;
	}
	else//找到最后一个节点
	{   
		SLTNode* ptail = * pphead;
		while (ptail->next)
		{
			ptail = ptail->next;
		}
		//ptail 指向的就是最后一个节点
		ptail->next = newmode;
	}

}

2.1头删尾删

2.1.1头删

要想实现头删 有一些细节需要注意

我们需要先新建一个next节点用来存放phead的下一个节点,然后再删除phead,最后将刚才新建的next节点设置为phead

否则就会出现以下的情况:刚刚将phead设置为当前头节点的下一个节点,然后把phead删除了,那么这个头节点也就找不到了

void SLTPopHead(SLTNode** pphead)
{
	assert(*pphead && pphead);
	SLTNode* next = (*pphead)->next;//存放头节点的下一个节点 防止丢失
	free(*pphead);
	*pphead = next;
}

2.2.2尾删

与尾插思路相似,如果当前链表只有一个节点那么直接删除即可。

如果有多个节点则需要遍历链表找到倒数第二个节点

void SLTPopTail(SLTNode** pphead)
{
	if ((*pphead)->next == NULL)
	{
		free(pphead);//只有一个节点
		*pphead == NULL;
		return;
	}
	SLTNode* cur = *pphead;
	while (cur->next->next!=NULL)
	{
		cur = cur->next;
	}
	//此时cur为倒数第二个节点
	free(cur->next);
	cur->next == NULL;
}

while循环条件是:cur(当前节点)的next节点的next不指向空

如果满足此条件,则cur右移一个节点。

如果移动到倒数第二个节点,那么cur的下一个节点是尾节点,其next指向空,满足条件,将其free掉并置空即可。

3 打印

链表的打印实现起来,要依靠while循环遍历链表,打印出每个节点的数据即可

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

4.销毁

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

这里要注意,新建一个pcur节点(当前节点)用来存放头节点指针,使用next节点存放pcur的下一个节点,然后遍历链表,先找到当前节点的下一个节点(next=pcur->next)再free掉当前节点,最后将当前节点后移一位。

整个循环结束后,最后删除头节点 

以上是单链表的最基本的插入和删除等代码,下一篇会涉及到指定位置的插入和删除,以及一些相关oj题目

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值