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