【数据结构与算法】单链表的增删查改(附源码)(下)

简介: 【数据结构与算法】单链表的增删查改(附源码)(下)

六.查找  插入  释放   打印

1.查找   SListfind

在插入和释放前,都需要调用 find 函数,来找到希望插入或是释放的位置。

1. SLNode* SListfind(SLNode* phead, SLdatatype x)
2. {
3.  SLNode* pos = phead;
4.  while (pos)
5.  {
6.    if (pos->data == x)
7.    {
8.      return pos;
9.    }
10.     pos = pos->next;
11.   }
12. }

2.插入  SListinsert

如果是链表中只有一个节点,就变成了头插,只需要调用头插函数就行了,如果是空表也不用担心,可以设置成不调用函数;

在插入前,需要找到指定位置 pos 的前驱 pre,

使pre->next=newnode  , newnode->next=pos

如图所示,假设在3的前一个位置插入数据:

 

1. void SListinsert(SLNode** pphead, SLNode* pos,SLdatatype x)
2. {
3.  SLNode* newnode = BuySListNode(x);
4.  if (pos->next == NULL)
5.  {
6.    SListpushfront(pphead, x);
7.  }
8.  else
9.  {
10.     SLNode* pre = *pphead;
11.     while (pre->next != pos)
12.     {
13.       pre = pre->next;
14.     }
15.     pre->next = newnode;
16.     newnode->next = pos;
17.   }
18. }

3.释放  SListerase

释放前:

1.如果只有一个节点,则直接释放头节点,再置为空即可;

2.如果不止一个节点,还需找到要释放的位置的前一个节点 pre ,将 pre 的 next 指向 pos 的next,然后再释放;

如图所示,假设要释放掉3这个节点:

 

1. void SListerase(SLNode** pphead, SLNode* pos, SLdatatype x)
2. {
3.  if (pos->next == NULL)
4.  {
5.    free(*pphead);
6.    *pphead = NULL;
7.  }
8.  else
9.  {
10.     SLNode* pre = *pphead;
11.     while (pre->next !=pos)
12.     {
13.       pre = pre->next;
14.     }
15.     pre->next = pos->next;
16.     free(pos);
17.   }
18. }

4.打印  SListprint

虽然可以直接用头节点 phead 遍历,但博主还是推荐定义一个新的结构体指针  cur  ,把phead 的值赋给 cur ,会显得更优雅;

注意这里的 while 里的式子要写成  cur  ,如果 写成 cur->next ,那么最终打印出来的结果会少一个节点的数据。

1. void SListprint(SLNode* phead)
2. {
3.  SLNode* cur = phead;
4.  while (cur != NULL)
5.  {
6.    printf("%d->", cur->data);
7.    cur = cur->next;
8.  }
9.  printf("NULL\n");
10. }

七.源码

1.SList.h

1. #define _CRT_SECURE_NO_WARNINGS
2. 
3. 
4. #include <stdio.h>
5. #include <stdlib.h>
6. #include <assert.h>
7. 
8. typedef int SLdatatype;
9. 
10. typedef struct SListNode
11. {
12.   SLdatatype data;
13.   struct SListNode* next;
14. }SLNode;
15. 
16. 
17. void SListprint(SLNode* phead);   //打印
18. 
19. void SListpushback(SLNode** pphead,SLdatatype x);   //尾插
20. 
21. void SListpushfront(SLNode** pphead, SLdatatype x);   //头插
22. 
23. void SListpopfront(SLNode** pphead);   //头删
24. 
25. void SListpopback(SLNode** pphead);   //尾删
26. 
27. SLNode* SListfind(SLNode* phead,SLdatatype x);   //查找
28. 
29. void SListinsert(SLNode** pphead, SLNode* pos,SLdatatype x);   //插入
30. 
31. void SListerase(SLNode** pphead, SLNode* pos, SLdatatype x);   //释放

2.SList.c

1. #define _CRT_SECURE_NO_WARNINGS
2. 
3. #include "SList.h"
4. 
5. 
6. void SListprint(SLNode* phead)
7. {
8.  SLNode* cur = phead;
9.  while (cur != NULL)
10.   {
11.     printf("%d->", cur->data);
12.     cur = cur->next;
13.   }
14.   printf("NULL\n");
15. }
16. 
17. 
18. SLNode* BuySListNode(SLdatatype x)
19. {
20.   SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
21.   assert(newnode);
22.   newnode->data = x;
23.   newnode->next = NULL;
24.   return newnode;
25. }
26. 
27. void SListpushback(SLNode** pphead,SLdatatype x)
28. {
29.   SLNode* newnode = BuySListNode(x);
30.   if (*pphead == NULL)
31.   {
32.     *pphead = newnode;
33.   }
34.   else
35.   {
36.     SLNode* tail = *pphead;  //寻找尾节点
37.     while (tail->next != NULL)
38.     {
39.       tail = tail->next;
40.     }
41.     tail->next = newnode;
42.   }
43. }
44. 
45. 
46. void SListpushfront(SLNode** pphead, SLdatatype x)
47. {
48.   SLNode* newnode = BuySListNode(x);
49.     newnode->next = *pphead;
50.     *pphead = newnode;
51. }
52. 
53. 
54. void SListpopfront(SLNode** pphead)
55. {
56.   if (*pphead == NULL)
57.   {
58.     return;
59.   }
60.   else
61.   {
62.     SLNode* next = (*pphead)->next;
63.     free(*pphead);
64.     *pphead = next;
65.   }
66. }
67. 
68. 
69. void SListpopback(SLNode** pphead)
70. {
71.   if (*pphead == NULL)
72.   {
73.     return;
74.   }
75.   else if ((*pphead)->next == NULL)
76.   {
77.     free(*pphead);
78.     *pphead = NULL;
79.   }
80.   else
81.   {
82.     SLNode* pre = NULL;
83.     SLNode* tail = *pphead;
84.     while (tail->next != NULL)
85.     {
86.       pre = tail;
87.       tail = tail->next;
88.     }
89.     pre->next = NULL;
90.   }
91. }
92. 
93. 
94. SLNode* SListfind(SLNode* phead, SLdatatype x)
95. {
96.   SLNode* pos = phead;
97.   while (pos)
98.   {
99.     if (pos->data == x)
100.    {
101.      return pos;
102.    }
103.    pos = pos->next;
104.  }
105. }
106. 
107. 
108. void SListinsert(SLNode** pphead, SLNode* pos,SLdatatype x)
109. {
110.  SLNode* newnode = BuySListNode(x);
111.  if (pos->next == NULL)
112.  {
113.    SListpushfront(pphead, x);
114.  }
115.  else
116.  {
117.    SLNode* pre = *pphead;
118.    while (pre->next != pos)
119.    {
120.      pre = pre->next;
121.    }
122.    pre->next = newnode;
123.    newnode->next = pos;
124.  }
125. }
126. 
127. 
128. 
129. void SListerase(SLNode** pphead, SLNode* pos, SLdatatype x)
130. {
131.  if (pos->next == NULL)
132.  {
133.    free(*pphead);
134.    *pphead = NULL;
135.  }
136.  else
137.  {
138.    SLNode* pre = *pphead;
139.    while (pre->next !=pos)
140.    {
141.      pre = pre->next;
142.    }
143.    pre->next = pos->next;
144.    free(pos);
145.  }
146. }

3.test.c

博主写的主函数只是用来测试单链表的,写起主函数来也不难,大家可以自行编写。

1. #include "SList.h"
2. 
3. 
4. void testSList1()
5. {
6.  SLNode* plist = NULL;
7. 
8.  SListpushback(&plist,1);
9.  SListpushback(&plist,2);
10.   SListpushback(&plist,3);
11.   SListpushback(&plist,4);
12.   SListprint(plist);
13.   SListpushfront(&plist, 0);
14.   SListprint(plist);
15.   SListpopfront(&plist);
16.   SListpopfront(&plist);
17.   SListpopfront(&plist);
18.   SListprint(plist);
19.   SListpopback(&plist);
20.   SListpopback(&plist);
21.   SListpopback(&plist);
22.   SListprint(plist);
23. }
24. 
25. void testSList2()
26. {
27.   SLNode* plist = NULL;
28.   SListpushback(&plist, 1);
29.   SListpushback(&plist, 2);
30.   SListpushback(&plist, 3);
31.   SListpushback(&plist, 4);
32.   SLNode* pos = SListfind(plist, 3);
33.   if (pos)
34.   {
35.     SListinsert(&plist,pos, 20);
36.     SListprint(plist);
37.   }
38.   pos = SListfind(plist, 2);
39.   if (pos)
40.   {
41.     SListerase(&plist,pos,2);
42.     SListprint(plist);
43.   }
44. 
45. }
46. 
47. int main()
48. {
49.   //testSList1();
50.   testSList2();
51.   return 0;
52. }

八.单链表的一些问题

在单链表中,要想找到某一个数据,就需要从头节点开始,所以单链表是非随机存取的存储结构,且要想对单链表进行一些操作,总是要找到前驱节点,有时还需判断一些特殊情况,有什么办法能解决这些问题呢?

博主将在下篇双向带头循环链表中讲解,敬情期待~


🤩🥰本篇文章到此就结束了,如有错误或是建议,欢迎小伙伴们提出~😍😃

🐲👻希望可以多多支持博主哦~🥰😍

🤖🐯谢谢你的阅读~👻🦁


目录
相关文章
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
1128 9
|
7月前
|
算法 数据可视化 数据挖掘
基于EM期望最大化算法的GMM参数估计与三维数据分类系统python源码
本内容展示了基于EM算法的高斯混合模型(GMM)聚类实现,包含完整Python代码、运行效果图及理论解析。程序使用三维数据进行演示,涵盖误差计算、模型参数更新、结果可视化等关键步骤,并附有详细注释与操作视频,适合学习EM算法与GMM模型的原理及应用。
|
8月前
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
413 3
|
11月前
|
存储 自然语言处理 数据库
【数据结构进阶】AVL树深度剖析 + 实现(附源码)
在深入探讨了AVL树的原理和实现后,我们不难发现,这种数据结构不仅优雅地解决了传统二叉搜索树可能面临的性能退化问题,还通过其独特的平衡机制,确保了在任何情况下都能提供稳定且高效的查找、插入和删除操作。
832 19
|
12月前
|
存储 算法 Java
算法系列之递归反转单链表
递归反转链表的基本思路是将当前节点的next指针指向前一个节点,然后递归地对下一个节点进行同样的操作。递归的核心思想是将问题分解为更小的子问题,直到达到基本情况(通常是链表末尾)。
415 5
算法系列之递归反转单链表
|
11月前
|
数据库 C++
【数据结构进阶】红黑树超详解 + 实现(附源码)
本文深入探讨了红黑树的实现原理与特性。红黑树是一种自平衡二叉搜索树,通过节点着色(红/黑)和特定规则,确保树的高度接近平衡,从而实现高效的插入、删除和查找操作。相比AVL树,红黑树允许一定程度的不平衡,减少了旋转调整次数,提升了动态操作性能。文章详细解析了红黑树的性质、插入时的平衡调整(变色与旋转)、查找逻辑以及合法性检查,并提供了完整的C++代码实现。红黑树在操作系统和数据库中广泛应用,其设计兼顾效率与复杂性的平衡。
2484 3
|
11月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
12月前
|
机器学习/深度学习 自然语言处理 算法
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
3324 1
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
1042 4
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
721 16

热门文章

最新文章