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

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

六.查找  插入  释放   打印

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

八.单链表的一些问题

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

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


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

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

🤖🐯谢谢你的阅读~👻🦁


目录
相关文章
|
27天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
123 9
|
26天前
|
存储 搜索推荐 算法
【数据结构】树型结构详解 + 堆的实现(c语言)(附源码)
本文介绍了树和二叉树的基本概念及结构,重点讲解了堆这一重要的数据结构。堆是一种特殊的完全二叉树,常用于实现优先队列和高效的排序算法(如堆排序)。文章详细描述了堆的性质、存储方式及其实现方法,包括插入、删除和取堆顶数据等操作的具体实现。通过这些内容,读者可以全面了解堆的原理和应用。
63 16
|
22天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
66 8
|
22天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
60 7
|
26天前
|
C语言
【数据结构】二叉树(c语言)(附源码)
本文介绍了如何使用链式结构实现二叉树的基本功能,包括前序、中序、后序和层序遍历,统计节点个数和树的高度,查找节点,判断是否为完全二叉树,以及销毁二叉树。通过手动创建一棵二叉树,详细讲解了每个功能的实现方法和代码示例,帮助读者深入理解递归和数据结构的应用。
87 8
|
29天前
|
存储 C语言
【数据结构】手把手教你单链表(c语言)(附源码)
本文介绍了单链表的基本概念、结构定义及其实现方法。单链表是一种内存地址不连续但逻辑顺序连续的数据结构,每个节点包含数据域和指针域。文章详细讲解了单链表的常见操作,如头插、尾插、头删、尾删、查找、指定位置插入和删除等,并提供了完整的C语言代码示例。通过学习单链表,可以更好地理解数据结构的底层逻辑,提高编程能力。
55 4
|
2月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
34 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
1月前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
61 3
|
2月前
|
存储
[数据结构] -- 单链表
[数据结构] -- 单链表
26 1
|
2月前
|
Java C++ 索引
让星星⭐月亮告诉你,LinkedList和ArrayList底层数据结构及方法源码说明
`LinkedList` 和 `ArrayList` 是 Java 中两种常见的列表实现。`LinkedList` 基于双向链表,适合频繁的插入和删除操作,但按索引访问元素效率较低。`ArrayList` 基于动态数组,支持快速随机访问,但在中间位置插入或删除元素时性能较差。两者均实现了 `List` 接口,`LinkedList` 还额外实现了 `Deque` 接口,提供了更多队列操作。
26 3