【算法与数据结构】单链表
2026/9/17 19:21:16 网站建设 项目流程

一、单链表是什么?

二、单链表的应用

1.单链表节点的结构

2.打印链表函数实现

3.头插和尾插的函数实现

4.开辟空间函数

5,尾删链表函数实现

6,头删函数实现

7,链表查找函数实现

8,在指定位置之前或之后插入数据

9,删除与销毁


一、单链表是什么?

单链表的全称是:不代头单向不循环链表。

代头:也叫哨兵位,头节点是一种工具性节点,没有实际意义。

二、单链表的应用

1.单链表节点的结构

typedef int SLTDateType;//对节点date类新重命名 typedef struct SListNode { SLTDateType date; //数据的存储 struct SListNode* next; }SLTNode;

2.打印链表函数实现

//打印函数 void SLTPrint(SLTNode* phead) { SLTNode* pcur = phead; while (pcur) { printf("%d -> ", pcur->date); pcur = pcur->next; } printf("NULL"); printf("\n"); }

思路解释:

*函数接受头节点指针,保存到phead形参中

*为pcur赋值phead,保护phead原始值

*利用单链表单向行,遍历链表进行打印

*跳出while,一NULL结尾

3.头插和尾插的函数实现

//头插 void SLTPushHead(SLTNode** pphead, SLTDateType x) { assert(pphead); SLTNode* node0 = SLCreat(x); node0->next = *pphead;//给新开拓的链表next连上; *pphead = node0;//根据地址改值可以改变实参的内容 //首地址变了; } //尾插 void SLTPushBack(SLTNode** pphead, SLTDateType x) { assert(pphead); //*pphead就是第一个节点的之指针; //空链表和非空链表; SLTNode* nodex = SLCreat(x); if (*pphead == NULL) { *pphead = nodex; }else { //寻找最后的地址 SLTNode* ptail = *pphead; while (ptail->next) { ptail = ptail->next; } ptail->next = nodex;//总之就是让while里的NULL为nodex } }

思路解释:

*头插一定会改变phead的实参的内容,传递值才能改变实参

*尾插是有空链表和非空链表,所以穿二级指针来应对空链表要改变头节点的情况

*用ptail找到最后的节点来尾插

4.开辟空间函数

//开辟地址的函数 SLTNode* SLCreat(SLTDateType x) { SLTNode* nodex = (SLTNode*)malloc(sizeof(SLTNode)); nodex->date = x; nodex->next = NULL; return nodex; }

5,尾删链表函数实现

//尾巴删 void SLTPopBack(SLTNode** pphead) { assert(pphead && *pphead); //链表只有一个节点 if ((*pphead)->next == NULL) { free(*pphead); *pphead = NULL; } else { //链表有多个节点时 SLTNode* ptail = *pphead; SLTNode* prev = *pphead; while (ptail->next) { prev = ptail; ptail = ptail->next; } free(ptail); ptail = NULL; prev->next = NULL; } }

注意:

*free之后要置空

*分为有一个节点的链表,和有多个链表的两种情况

6,头删函数实现

//头删 void SLTPopFront(SLTNode** pphead) { assert(pphead && *pphead); SLTNode* next = (*pphead)->next;// free(*pphead); *pphead = next; }

7,链表查找函数实现

//查找 SLTNode* SLTFind(SLTNode* phead, SLTDateType x) { assert(phead); SLTNode* pcur = phead; while (pcur) { if (pcur->date == x) { return pcur; } pcur = pcur->next; } return NULL; }

注意:

*x是不一定存在的

*while循环里加if判断

*if判断完跳出或是直接return

总结


8,在指定位置之前或之后插入数据

//在指定位置之前 void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x) { //默认指定位置存在 assert(pphead && *pphead); assert(pos); if (pos == *pphead) { SLTPushHead(pphead, x); } else { SLTNode* new = SLCreat(x); SLTNode* prev = *pphead; while (prev->next != pos) { prev = prev->next; } prev->next = new; new->next = pos; } } //在指定位置之后扎入 void SLTInsertAfter(SLTNode* pos, SLTDateType x) { assert(pos); SLTNode* new = SLCreat(x); new->next = pos->next; pos->next = new; }

( A )在pos指定位置之前插入数据

*默认指定pos存在,且不知空链表

*如果插在首节点的前面,则会改变首节点指针--->导致改变实参直接头插即可

*else的情况无非就是在prev和pos的之间插入数据

( B )在之后插入数据

*单项链表可以直接找到pos后面的指针pos->next

9,删除与销毁

//删除指定位置的内容 void SLErase(SLTNode** pphead, SLTNode* pos) { assert(pphead && *pphead); assert(pos); if (pos == *pphead) { //前删 SLTPopFront(pphead); } else { SLTNode* prev = *pphead; while (prev->next != pos) { prev = prev->next; } prev->next = pos->next; free(pos); pos = NULL; } } //删除pos之后的 void SLEraseAfter(SLTNode* pos) { assert(pos && pos->next); SLTNode* del = pos->next; pos->next = del->next; free(del); del = NULL; } //销毁链表 void SLTDestroy(SLTNode** pphead) { assert(pphead); SLTNode* pcur = *pphead; while (pcur) { SLTNode* next = pcur->next; free(pcur); pcur = next; } *pphead = NULL; }

相似巧思

(1)当中的prev起到的保护实参内容的作用

(2)del是pos->next,则del->next就是要与pos链接的节点

(3)pcur起到与prev相似的作用,next就是储存盒子,free之后再赋值


总结

这是单链表中函数实现的代码,多记多练,没事打开练一练

注意当中的坑,笔记结束!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询