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

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

六.查找  插入  释放   打印

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. }

八.单链表的一些问题

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

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


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

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

🤖🐯谢谢你的阅读~👻🦁


目录
相关文章
|
24天前
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
77 3
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
161 7
|
2月前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
133 8
|
3月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
58 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
3月前
|
存储
[数据结构] -- 单链表
[数据结构] -- 单链表
32 1
|
3月前
|
存储
【数据结构】——单链表实现
【数据结构】——单链表实现
|
3月前
|
存储
数据结构2——单链表
数据结构2——单链表
42 1
|
3月前
|
存储
数据结构(单链表)
数据结构(单链表)
25 0
|
3月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
107 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
3月前
|
机器学习/深度学习 存储 缓存
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
58 1
数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍