单链表基本操作的实现与解析(补充)

news/2025/3/10 10:01:28/

目录

一、引言

二、代码实现

遍历考虑情况

三、操作解析

查找操作(sltfind函数)

前插操作(sltinsert函数)

后插操作(sltinsertafter函数)

前删操作(slterase函数)

后删操作(slteraseafter函数)

四、应用场景与拓展

应用场景

拓展

五、总结


一、引言

作者主页:共享家9527-CSDN博客

作者小仓库:https://blog.csdn.net/nplplus/category_12904039.html?fromshare=blogcolumn&sharetype=blogcolumn&sharerId=12904039&sharerefer=PC&sharesource=nplplus&sharefrom=from_link

单链表作为一种基础且常用的数据结构,在计算机科学领域应用广泛。它以节点为基本单元,通过指针构建节点间的线性关系,每个节点包含数据域与指向下一节点的指针域。这种链式存储结构相比数组,在内存使用上更加灵活,无需连续的内存空间。在实际编程中,对单链表执行查找、插入和删除等操作是数据处理和算法设计的基础,理解和掌握这些操作,对后续学习复杂数据结构算法至关重要。本文将结合具体的C语言代码,深入且细致地剖析单链表的这些基本操作。

二、代码实现

c#include <stdio.h>#include <stdlib.h>#include <assert.h>// 定义单链表节点结构typedef int SLTDataType;typedef struct SLTNode {SLTDataType data;struct SLTNode* next;} SLTNode;// 创建新节点的函数SLTNode* BuySLTNode(SLTDataType x) {SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL) {perror("malloc");return NULL;}newnode->data = x;newnode->next = NULL;return newnode;}// 查找函数SLTNode* sltfind(SLTNode* pphead, int x) {SLTNode* cur = pphead;while (cur) {if (cur->data == x) {return cur;}else {cur = cur->next;}}return NULL;}// pos前插函数void sltinsert(SLTNode** pphead, SLTNode* pos, int x) {assert(pphead);assert(pos);if (pos == *pphead) {SLTNode* newnode = BuySLTNode(x);newnode->next = *pphead;*pphead = newnode;}else {SLTNode* pre = *pphead;while (pre->next != pos) {pre = pre->next;}SLTNode* newnode = BuySLTNode(x);pre->next = newnode;newnode->next = pos;}}// pos后插函数void sltinsertafter(SLTNode* pos, int x) {assert(pos);SLTNode* newnode = BuySLTNode(x);newnode->next = pos->next;pos->next = newnode;}// pos前删函数void slterase(SLTNode** pphead, SLTNode* pos) {assert(pphead);assert(pos);if (pos == *pphead) {SLTNode* temp = *pphead;*pphead = (*pphead)->next;free(temp);}else {SLTNode* pre = *pphead;while (pre->next != pos) {pre = pre->next;}pre->next = pos->next;free(pos);}}// pos后删函数,此处修改函数名为slteraseaftervoid slteraseafter(SLTNode* pos) {assert(pos);assert(pos->next);SLTNode* mid = pos->next;pos->next = pos->next->next;free(mid);mid = NULL;}

遍历考虑情况

三、操作解析

查找操作(sltfind函数)

- 函数功能:此函数用于在单链表中查找特定数据值 x 所在的节点。

- 参数:接受链表头指针 pphead 和要查找的值 x 。

- 执行过程:从链表头节点开始,通过 while 循环依次遍历每个节点。在每次循环中,将当前节点 cur 的数据与目标值 x 进行比较。若相等,说明找到目标节点,直接返回该节点指针;若不相等,则将 cur 指向下一个节点继续查找。当遍历完整个链表仍未找到匹配值时,返回 NULL 。例如,在一个包含节点数据为 1, 3, 5, 7 的链表中查找值为 5 的节点,当 cur 遍历到第三个节点时,数据匹配,函数返回该节点指针。

前插操作(sltinsert函数)

- 函数功能:在指定位置 pos 之前插入一个新节点,新节点的数据为 x 。

- 参数:需要链表头指针的二级指针 pphead (用于修改头指针)、插入位置的指针 pos 以及要插入的值 x 。

- 执行过程:首先使用 assert 进行断言检查,确保传入的头指针和插入位置指针有效。若插入位置 pos 恰好是头节点,直接创建新节点,让新节点的 next 指向原头节点,然后更新头指针指向新节点,这样新节点就插入到了头节点之前。若 pos 不是头节点,则从链表头节点开始,通过 while 循环查找 pos 的前一个节点 pre 。找到后,创建新节点,将 pre 的 next 指向新节点,新节点的 next 再指向 pos ,完成插入操作。比如,在链表 1 -> 3 -> 5 中,要在值为 3 的节点前插入值为 2 的节点,先找到值为 1 的节点(即 3 节点的前一个节点),然后按上述步骤插入新节点,链表变为 1 -> 2 -> 3 -> 5 。

后插操作(sltinsertafter函数)

- 函数功能:在指定节点 pos 之后插入一个新节点,新节点的数据为 x 。

- 参数:接受插入位置的指针 pos 和要插入的值 x 。

- 执行过程:先使用 assert 检查 pos 是否有效。然后创建新节点,将新节点的 next 指针指向 pos 的下一个节点,再将 pos 的 next 指针指向新节点。例如,在链表 1 -> 3 -> 5 中,在值为 3 的节点后插入值为 4 的节点,新节点 4 的 next 指向原 3 节点的下一个节点 5 ,然后 3 节点的 next 指向新节点 4 ,链表变为 1 -> 3 -> 4 -> 5 。

前删操作(slterase函数)

- 函数功能:删除指定位置 pos 的节点。

- 参数:接受链表头指针的二级指针 pphead 和要删除节点的指针 pos 。

- 执行过程:首先进行断言检查,保证头指针和要删除节点指针有效。若要删除的节点 pos 是头节点,先保存头节点到临时变量 temp ,然后将头指针更新为原头节点的下一个节点,最后释放 temp 节点的内存。若 pos 不是头节点,则从链表头节点开始,通过 while 循环找到 pos 的前一个节点 pre 。找到后,将 pre 的 next 指针直接指向 pos 的下一个节点,然后释放 pos 节点的内存。比如,在链表 1 -> 3 -> 5 中删除值为 3 的节点,先找到值为 1 的节点(即 3 节点的前一个节点),然后修改指针,将 1 节点的 next 指向 5 节点,再释放 3 节点的内存,链表变为 1 -> 5 。

后删操作(slteraseafter函数)

- 函数功能:删除指定节点 pos 之后的节点。

- 参数:接受删除位置的指针 pos 。

- 执行过程:先使用 assert 检查 pos 及其下一个节点是否有效。然后保存 pos 的下一个节点到 mid ,将 pos 的 next 指针指向 mid 的下一个节点(即 pos 的下下个节点),最后释放 mid 节点的内存。例如,在链表 1 -> 3 -> 5 -> 7 中,删除值为 3 节点后的节点(即值为 5 的节点),先保存 5 节点到 mid ,然后将 3 节点的 next 指向 7 节点,再释放 5 节点的内存,链表变为 1 -> 3 -> 7 。

四、应用场景与拓展

应用场景

数据管理系统:在小型数据管理系统中,单链表可用于存储和管理数据记录,如简单的学生信息管理系统,每个学生信息作为一个节点,通过单链表方便地进行插入、删除和查找操作。

缓存机制:在一些简单的缓存实现中,单链表可以用来管理缓存数据,通过删除最近最少使用的节点(后删操作)来为新数据腾出空间。

拓展

双向链表:单链表只能单向遍历,而双向链表在单链表基础上增加了指向前一个节点的指针,使得遍历更加灵活,可实现从后向前的查找和删除等操作。

循环链表:循环链表的尾节点指向头节点,形成一个环形结构,在一些需要循环处理数据的场景中,如循环队列的实现,循环链表能发挥独特的优势。

五、总结

通过上述代码和解析,我们对单链表的基本操作有了全面且深入的理解。这些操作是处理单链表的基石,在实际的算法设计和数据处理中频繁使用。掌握好单链表的操作,不仅能提升编程能力,更能为进一步学习其他复杂的数据结构算法,如栈、队列、树等,打下坚实的基础。在实际应用中,应根据具体需求选择合适的数据结构和操作方法,以实现高效的数据处理和算法设计。


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

相关文章

【Hadoop】如何理解MapReduce?

MapReduce 是一种用于处理大规模数据集的编程模型和计算框架。它的核心思想是将复杂的计算任务分解为两个简单的阶段&#xff1a;Map&#xff08;映射&#xff09; 和 Reduce&#xff08;归约&#xff09;。通过这种方式&#xff0c;MapReduce 可以高效地并行处理海量数据。 一…

利用LLMs准确预测旋转机械(如轴承)的剩余使用寿命(RUL)

研究背景 研究问题&#xff1a;如何准确预测旋转机械&#xff08;如轴承&#xff09;的剩余使用寿命&#xff08;RUL&#xff09;&#xff0c;这对于设备可靠性和减少工业系统中的意外故障至关重要。研究难点&#xff1a;该问题的研究难点包括&#xff1a;训练和测试阶段数据分…

力扣1463. 摘樱桃 II

力扣1463. 摘樱桃 II 题目 题目解析及思路 题目要求返回从左上角和右上角分别出发两个机器人摘樱桃的最大数量、 每个机器人可以往左下&#xff0c;正下&#xff0c;右下三个方向走 定义f[i][j1][k1]表示一个机器人从(i,j)出发&#xff0c;一个机器人从(i,k)出发的最多摘樱…

Oracle RAC配置原理详解:构建高可用与高性能的数据库集群

在现代企业级应用中&#xff0c;数据库的高可用性和高性能是至关重要的。Oracle Real Application Clusters&#xff08;RAC&#xff09;是Oracle数据库提供的一种集群解决方案&#xff0c;能够将多个数据库实例部署在不同的服务器上&#xff0c;实现负载均衡和故障切换&#x…

Banana Pi OpenWRT One Wifi6 OpenWrt社区官方开源路由器评测

第一款不可破解、开源、版权软件、符合 FCC、CE 和 RoHS 的维修权路由器 OpenWRT项目今年已经20岁了&#xff0c;为了纪念这一时刻&#xff0c;Banana Pi OpenWrt One/AP-24.XY路由器开发系统已经上市。这是OpenWRT团队与硬件公司的第一个联合项目。选择 Banana Pi&#xff0c;…

中国云计算市场2025年四大趋势与展望

一、云智融合大模型引领市场增量 趋势概述&#xff1a;AI驱动的新增长极 2025年&#xff0c;中国云计算市场正式迈入“大模型工业化应用元年”&#xff0c;标志着云与AI的深度融合从理论探讨和概念验证阶段&#xff0c;走向了成为企业核心竞争力支柱的关键时期。IDC的预测数据显…

高频 SQL 50 题(基础版)_610. 判断三角形

思路 # Write your MySQL query statement below select x,y,z, case when xy>z and xz>y and yz>x then Yes else No end as triangle from Triangle

深度链接技术解析:openinstall如何通过场景还原优化用户体验?

在移动应用生态中&#xff0c;用户从点击广告到完成核心行为&#xff08;如下单、注册、观看内容&#xff09;&#xff0c;往往需要跨越网页、应用商店、App内部页面等多个触点。这一过程中&#xff0c;“跳转断层”成为用户流失的最大黑洞——用户可能因为路径中断、重复操作或…