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

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

六.查找  插入  释放   打印

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

八.单链表的一些问题

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

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


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

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

🤖🐯谢谢你的阅读~👻🦁


目录
相关文章
|
3天前
|
C++
数据结构(循环单链表
数据结构(循环单链表
9 2
|
3天前
|
C++
数据结构(单链表
数据结构(单链表
6 0
|
6天前
|
存储
[数据结构]单链表(从0->1)
[数据结构]单链表(从0->1)
|
17天前
|
存储
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
数据结构基础:一篇文章教你单链表(头插,尾插,查找,头删等的解析和代码)
|
18天前
|
设计模式 算法 Java
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
[设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
|
20天前
|
存储
数据结构:4、链表之单链表
数据结构:4、链表之单链表
12 0
|
25天前
|
存储 算法
单链表——“数据结构与算法”
单链表——“数据结构与算法”
|
26天前
|
算法 C#
winform车牌识别源码(纯算法)
使用C#和Winform开发的纯算法车牌识别系统,无需依赖外部框架。通过去雾、灰度化、均衡化、中值滤波等步骤实现车牌定位和识别。包含详细步骤及源码,适合学习研究。演示视频:[BV1yq4y1a7cb](https://www.bilibili.com/video/BV1yq4y1a7cb/?spm_id_from=333.337.search-card.all.click&vd_source=6d6d1b4c92d36f8d9ca8a23a286bae20)。
|
1月前
|
算法 索引
【算法与数据结构】深入二叉树实现超详解(全源码优化)
【算法与数据结构】深入二叉树实现超详解(全源码优化)
|
1月前
|
算法 C语言
【算法与数据结构】 C语言实现单链表队列详解2
【算法与数据结构】 C语言实现单链表队列详解