单链表难?带你速通!

目录

1>>单链表介绍

2>>实现单链表

2.1>>单链表的尾插

2.2>>单链表的尾删   

    ​编辑

2.3>>头插

2.4>>附录:代码

3>>总结


1>>单链表介绍

        随着顺序表的结束,单链表自然就来了,这两个东西物理上有关系吗?没有,只是我们逻辑上认为学习完顺序表就要学习单链表,这就是单链表,什么没听懂?单链表的定义就是逻辑结构链接,而物理结构不连接。可以将它看成一节一节的火车,而假设火车原本有abcd节车厢,别的火车借走cd,之后换回来e和g那火车就是abeg了,这四个车厢物理结构并不相通,而逻辑结构是相通的,那么回过头,把火车看作单链表,一节节车厢就代表一个个结点,因此,这就是单链表。

这样看是不是形象生动,数据就是乘客,下一节点地址就是火车之间的连接器。

2>>实现单链表

首先跟顺序表一样,需要三个文件

这里取single + list的组合来命名。

这里附上顺序表链接,若是没看的也可以看看鄙人的拙文:顺序表各项功能的实现-CSDN博客

头文件觉得需要包含的项目都可以先写上去。

在另外两个文件包含头文件。

创建一个sldatetype方便修改存放数据的类型,创建单链表所需要的结构体以及元素。

上述基础步骤完成以后,就可以实现单链表的部分功能了。

2.1>>单链表的尾插

        

尾插的声明,包括二级指针pphead(两个p方便自己和大家看是二级指针),x表示要插入的数据。

为什么这里是二级指针?因为创建的是结构体指针,等会要传的是phead的地址,phead指向了结构体的两个元素,要想在函数内对这两个元素也就是phead,注意是phead,在test创建的phead里的元素进行更改和操作就要传phead的地址,否则:拿一个新的结构体指针进行接收,那么在函数体内更改,都不会对phead实施操作!!!

现在看看尾插的实现,看不懂也没事,接下来我会一一解说:

首先,进来我们需要判断pphead也就是你传进来的地址是不是空地址,如果是则进行断言,若不是,开始步骤:要实现插入,我们需要创建新节点,这里用buynode(购买结点)写,把要插入的数传入buynode,新节点都要进行开辟空间,大小为结构体大小,类型为结构体指针类型,这样这个结点才能指向结构体内的元素,如果开辟了一个空指针,那么输出错误信息。不然让x赋值给node指向的date部分

然后指向的next赋值为NULL表示后面没地址(车厢)了。

返回地址用newnode接收

如果传进来的就是一个空地址,也就是说现在还没车厢,*pphead就是传进来的phead,将newnode直接给它

如果不是,那么就要遍历一遍单链表,直到ptail指向的下一个地址为空,说明ptail就是最后一个地址,将它的next置为newnode就好,那么至此,尾插结束!


2.2>>单链表的尾删   

    

声明就是类似的,不多赘述啦。

        

首先进来,判断删除的是一个空指针和传进来的是一个空指针。

判断,如果删除的是第一个结点,那么直接对*pphead进行free,并且置为空指针

如果不是,需要两个结构体指针辅助,一个pend始终慢pcur一步以这图为例子,当pcur为最后一个时,pend为倒数第二个,我们要删除最后一个结点,只需要释放最后一个结点,并且pend的next置为空指针就好,因此尾删就解决了

2.3>>头插

        

头插的实现声明和尾插类似,这里不多嗦啦。

这里进来首先判断是否传了空指针,然后创建一个新结点,直接将新结点的下一个地址指向*pphead也就是链表头部地址(火车头),然后将链表头部(火车头)改成newnode也就是新结点地址就好啦

2.4>>附录:代码

Slist.c

#include"Slist.h"

void SLprint(SLN* phead) {
	SLN* pcur = phead;
	while (pcur) {
		printf("%d -> ", pcur->date);
		pcur = pcur->next;
	}
		printf("NULL\n");
}

SLN* buynode(sldatetype x) {
	SLN* node = (SLN*)malloc(sizeof(SLN));
	if (node == NULL) {
		perror("malloc");
		exit(1);
	}
	node->date = x;
	node->next = NULL;
	return node;
}
void SLtailc(SLN** pphead, sldatetype x) {
	assert(pphead);
	SLN* newnode = buynode(x);
	if (*pphead == NULL) {
		*pphead = newnode;
	}
	else {
		SLN* ptail = *pphead;
		while (ptail->next) {
			ptail = ptail->next;
		}
		ptail->next = newnode;
	}
}

void SLtaild(SLN** pphead) {
	assert(pphead && *pphead);
	if ((*pphead)->next == NULL) {
		free(*pphead);
		*pphead = NULL;
	}
	else {
		SLN* pcur = *pphead;
		SLN* pend = NULL;
		while (pcur->next) {
			pend = pcur;
			pcur = pcur->next;
		}
		pend->next = NULL;
		free(pcur);
		pcur = NULL;
	}
}

void SLfrontc(SLN** pphead, sldatetype x) {
	assert(pphead);
	SLN* newnode = buynode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

Slist.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<assert.h>

typedef int sldatetype;

typedef struct SLnode {
	sldatetype date;
	struct SLnode* next;
}SLN;

void SLprint(SLN* phead);

void SLtailc(SLN** pphead, sldatetype x);//尾插,尾部tail+插入c

void SLtaild(SLN** pphead);//尾删,尾部tail+删除d

void SLfrontc(SLN** pphead, sldatetype x);//头插

test.c

#include"Slist.h"


void test() {
	SLN* phead = NULL;
	SLtailc(&phead, 6);
	SLprint(phead);
	SLfrontc(&phead, 55);
	SLprint(phead);
	SLfrontc(&phead, 44);
	SLprint(phead);
	SLtailc(&phead, 77);
	SLprint(phead);
	SLtaild(&phead);
	SLprint(phead);SLtaild(&phead);
	SLprint(phead);SLtaild(&phead);
	SLprint(phead);
}
int main() {
	test();
	return 0;
}

3>>总结

        今天学习了数据结构的单链表内容,实现了单链表里的尾插,头插,尾删,希望能帮助到大家,期待与你下篇再见!明天继续更新,多多支持小编,谢谢大家

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

枫の大一

谢谢大佬,我会三连你的文章

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

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

打赏作者

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

抵扣说明:

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

余额充值