单链表专题(上)

news/2025/2/3 16:50:02/

链表的定义与创建

线性表: 1. 物理结构上不一定是线性的

                2. 逻辑结构上一定是线性的

链表是一种物理存储结构上非连续,非顺序的存储结构

链表也是线性表的一种,但是在物理结构上不是连续的

链表是由一个一个的节点组成,需要数据的时候只需要申请空间即可

节点包含两个组成部分: 1. 存储的数据

                                         2. 指向下一个节点的指针

//节点的结构演示
struct SListNode   //single list node
{int data;struct SListNode* next;  //指向下一个节点的指针
}

下面我们将详细的进行链表节点的定义:

//定义节点的结构
//数据 + 指向下一个节点的指针
typedef int SLTDataType;  //由于数据不止 int 一种类型,所以统一用 SLTDataType 表示 
typedef struct SListNode {SLTDataType data;struct SListNode* next;
}SLTNode;

这里我们将struct SListNode 统一改写成 SLTNode

接下来,我们来学习创建几个节点:

//创建四个节点
SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
node1->data = 1;
SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
node2->data = 2;
SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
node3->data = 3;
SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
node4->data = 4;
//将四个节点连接起来
node1->next = node2;
node2->next = node3;
node3->next = node4;
node4->next = NULL;

由于创建的新节点的内存情况未知,所以使用 malloc 来动态分配内存。realloc 主要用于调整已分配内存块的大小

链表的打印

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

但是我们一般不会像那样创建节点,而是给一个空链表去插入数据,所以下面是链表的尾插

链表的尾插

想找到进行尾插,要先找到尾节点,再将尾节点和新节点连接起来

注意: 我们在尾插头插等等时,都需要用到malloc创建新的空间,重复的书写会使代码显得冗长,所以我们封装一个函数专门用于开辟空间

SLTNode* SLTBuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//判断空间是否开辟成功if (newnode == NULL){perror("malloc failed !");exit(1); //用非零的数表示非正常退出}newnode->data = x;newnode->next = NULL;return newnode;
}

有了创建控件函数后,我们开始写尾插代码:

void SLTPushBack(SLTNode* phead, SLTDataType x)
{SLTNode* newnode = SLTBuyNode(x);//先找尾SLTNode* ptail = phead; while (ptail->next != NULL){ptail = ptail->next;}//此时ptail指向的就是尾节点ptail->next = newnode;
}

请注意,这里的原链表并不知道是否是空链表,若为空,则对空指针解引用是非法的。所以需要对两种情况进行讨论:

void SLTPushBack(SLTNode* phead, SLTDataType x)
{//空链表情况SLTNode* newnode = SLTBuyNode(x);if (phead == NULL){phead = newnode;}else{//非空链表情况//先找尾SLTNode* ptail = phead; while (ptail->next != NULL){ptail = ptail->next;}//此时ptail指向的就是尾节点ptail->next = newnode;}    
}

这里用个很重大的问题,我们传入实参 plist ,而我们需要形参改变实参,plist虽然也是指针,但他存储着一个结构体的地址,我们现在就是要修改这个地址的相关内容,所以我们需要使用二级指针来传址调用

下面是一些对应关系:

第一个节点

*plist

**pphead

指向第一个节点的指针

plist

*pphead

指向第一个节点的指针的地址

&plist

pphead

//链表的尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);//空链表情况SLTNode* newnode = SLTBuyNode(x);if (*pphead == NULL){*pphead = newnode;}else{//非空链表情况//先找尾SLTNode* ptail = *pphead; while (ptail->next != NULL){ptail = ptail->next;}//此时ptail指向的就是尾节点ptail->next = newnode;}
}

由于节点的地址的地址不能为空,所以再加入断言,尾插代码就写好了。

void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);  //链表不能为空SLTNode* prev = *pphead;SLTNode* ptail = *pphead;while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;prev->next = NULL;
}

链表的头插(相对简单)

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

链表的尾删

思路为先找到尾节点,将尾节点释放掉,由于释放了尾节点后,尾节点的上一个节点依然指向尾节点,所以还需将上一个节点置零

void SLTPopBack(SLTNode** pphead)
{assert(pphead && *pphead);  //链表不能为空SLTNode* prev = *pphead;SLTNode* ptail = *pphead;while (ptail->next){prev = ptail;ptail = ptail->next;}free(ptail);ptail = NULL;prev->next = NULL;
}

当链表只有一个节点的时候,此时尾节点的上一个节点并不实际存在,所以需要单独讨论

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


http://www.ppmy.cn/news/1569005.html

相关文章

EasyExcel使用详解

文章目录 EasyExcel使用详解一、引言二、环境准备与基础配置1、添加依赖2、定义实体类 三、Excel 读取详解1、基础读取2、自定义监听器3、多 Sheet 处理 四、Excel 写入详解1、基础写入2、动态列与复杂表头3、样式与模板填充 五、总结 EasyExcel使用详解 一、引言 EasyExcel 是…

手机连接WIFI可以上网,笔记本电脑连接WIFI却不能上网? 解决方法?

原因:DNS受污染了 解决办法 step 1:清空域名解析记录(清空DNS) ipconfig /flushdns (Windows cmd命令行输入) step 2:重新从DHCP 获取IP ipconfig /release(释放当前IP地址) ipconfig /renew &…

从0开始,来看看怎么去linux排查Java程序故障

一,前提准备 最基本前提:你需要有liunx环境,如果没有请参考其它文献在自己得到local建立一个虚拟机去进行测试。 有了虚拟机之后,你还需要安装jdk和配置环境变量 1. 安装JDK(以OpenJDK 17为例) 下载JDK…

[权限提升] Windows 提权 维持 — 系统错误配置提权 - Trusted Service Paths 提权

关注这个专栏的其他相关笔记:[内网安全] 内网渗透 - 学习手册-CSDN博客 0x01:Trusted Service Paths 提权原理 Windows 的服务通常都是以 System 权限运行的,所以系统在解析服务的可执行文件路径中的空格的时候也会以 System 权限进行解析,如果我们能够利用这一特性,就有…

常见字符串相关题目

找往期文章包括但不限于本期文章中不懂的知识点: 个人主页:我要学编程(ಥ_ಥ)-CSDN博客 所属专栏: 优选算法专题 目录 14.最长公共前缀 5.最长回文子串 67.二进制求和 43.字符串相乘 14.最长公共前缀 题目: 编写一个函数来查…

本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操

本地部署DeepSeek开源多模态大模型Janus-Pro-7B实操 Janus-Pro-7B介绍 Janus-Pro-7B 是由 DeepSeek 开发的多模态 AI 模型,它在理解和生成方面取得了显著的进步。这意味着它不仅可以处理文本,还可以处理图像等其他模态的信息。 模型主要特点:Permalink…

Flink报错Caused by: java.io.FileNotFoundException: /home/wc.txt

当在提交一个flink任务报如下的错误时: Caused by: java.io.FileNotFoundException: /home/wc.txt (没有那个文件或目录)at java.io.FileInputStream.open0(Native Method)at java.io.FileInputStream.open(FileInputStream.java:195)at java.io.FileInputStream.&…

tomcat shutdown.sh不能关闭tomcat 进程

目录 背景及问题表现 处理办法 1、修改setclasspath.sh里的PID环境变量: 背景及问题表现 在上一篇文章中,记录了Debian 12环境里 设置tomcat定时重启的过程,详见:Debian 设定 tomcat 定时重启-CSDN博客 其中我设定的用于重启的…