【数据结构】双向链表-C语言版

简介: 【数据结构】双向链表-C语言版

带头结点的双向循环链表的实现

038-List.h

1. #define  _CRT_SECURE_NO_WARNINGS  1
2. 
3. //带头结点
4. 
5. typedef int LTDataType;
6. typedef struct ListNode
7. {
8.  struct ListNode* prev;
9.  struct ListNode* next;
10.   LTDataType data;
11. }ListNode;
12. 
13. //创建新结点
14. ListNode* BuyListNode(LTDataType x);
15. 
16. //初始化
17. ListNode* ListInit();
18. 
19. //尾插
20. void ListPushBack(ListNode* phead, LTDataType x);
21. 
22. //头插
23. void ListPushFront(ListNode* phead, LTDataType x);
24. 
25. //尾删
26. void ListPopBack(ListNode* phead);
27. 
28. //头删
29. void ListPopFront(ListNode* phead);
30. 
31. //查找
32. ListNode* ListFind(ListNode* phead, LTDataType x);
33. 
34. //前一个位置插入
35. void ListInsert(ListNode* pos, LTDataType x);
36. 
37. //删除pos位
38. void ListErase(ListNode* pos);
39. 
40. //链表判空,空返回1,非空返回0
41. int ListEmpty(ListNode* phead);
42. 
43. //链表大小
44. int ListSize(ListNode* phead);
45. 
46. //链表销毁
47. void ListDestroy(ListNode* phead);

038-List.c

1. #define  _CRT_SECURE_NO_WARNINGS  1
2. #include "038-List.h"
3. #include<stdio.h>
4. #include<stdlib.h>
5. #include<assert.h>
6. 
7. //带头结点
8. 
9. void ListPrint(ListNode* phead)
10. {
11.   ListNode* cur = phead->next;
12.   while (cur != phead)
13.   {
14.     printf("%d ", cur->data);
15.     cur = cur->next;
16.   }
17.   printf("\n");
18. 
19. }
20. 
21. //创建新结点
22. ListNode* BuyListNode(LTDataType x)
23. {
24.   ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
25.   newNode->prev = NULL;
26.   newNode->next = NULL;
27.   newNode->data = x;
28. 
29.   return newNode;
30. }
31. 
32. //初始化
33. ListNode* ListInit()
34. {
35.   ListNode* phead = BuyListNode(0);
36.   phead->prev = phead;
37.   phead->next = phead;
38. 
39.   return phead;
40. }
41. 
42. //尾插
43. void ListPushBack(ListNode* phead, LTDataType x)
44. {
45.   ListNode* tail = phead->prev;
46.   ListNode* newNode = BuyListNode(x);
47. 
48.   tail->next = newNode;
49.   newNode->prev = tail;
50.   newNode->next = phead;
51.   phead->prev = newNode;
52. }
53. 
54. //头插
55. void ListPushFront(ListNode* phead, LTDataType x)
56. {
57.   ListNode* first = phead->next;
58.   ListNode* newNode = BuyListNode(x);
59. 
60.   newNode->next = first;
61.   first->prev = newNode;
62.   phead->next = newNode;
63.   newNode->prev = phead;
64. }
65. 
66. //尾删
67. void ListPopBack(ListNode* phead)
68. {
69.   assert(phead);
70.   assert(phead->next != phead);
71. 
72.   ListNode* tail = phead->prev;
73.   ListNode* tailprev = tail->prev;
74. 
75.   free(tail);
76. 
77.   tailprev->next = phead;
78.   phead->prev = tailprev;
79. 
80. }
81. 
82. //头删
83. //如果只有一个结点,那么就有问题
84. void ListPopFront(ListNode* phead)
85. {
86.   assert(phead);
87.   assert(phead->next != phead);
88. 
89.   ListNode* first = phead->next;
90.   ListNode* second = first->next;
91. 
92.   free(first);
93. 
94.   phead->next = second;
95.   second->prev = phead;
96. 
97. }
98. 
99. //查找
100. ListNode* ListFind(ListNode* phead, LTDataType x)
101. {
102.  assert(phead);
103. 
104.  ListNode* cur = phead->next;
105.  while (cur != phead)
106.  {
107.    if (cur->data == x)
108.    {
109.      return cur;
110.    }
111.    cur = cur->next;
112.  }
113.  return NULL;
114. }
115. 
116. //在前一个位置插入
117. void ListInsert(ListNode* pos, LTDataType x)
118. {
119.  //assert(phead);
120.  ListNode* prev = pos->prev;
121.  ListNode* newNode = BuyListNode(x);
122. 
123.  newNode->next = pos;
124.  pos->prev = newNode;
125.  prev->next = newNode;
126.  newNode->prev = prev;
127. }
128. 
129. //删除pos位
130. void ListErase(ListNode* pos)
131. {
132.  ListNode* prev = pos->prev;
133.  ListNode* next = pos->next;
134. 
135.  prev->next = next;
136.  next->prev = prev;
137. 
138.  free(pos);
139. }
140. 
141. //链表判空,空返回1,非空返回0
142. int ListEmpty(ListNode* phead)
143. {
144.  return phead->next == phead ? 1 : 0;//头结点的下一个是否指向头结点自己
145. }
146. 
147. //链表大小
148. int ListSize(ListNode* phead)
149. {
150.  assert(phead);
151. 
152.  int size = 0;
153.  ListNode* cur = phead->next;
154.  while (cur != phead)
155.  {
156.    size++;
157.    cur = cur->next;
158.  }
159.  return size;
160. }
161. 
162. //链表销毁
163. void ListDestroy(ListNode* phead)
164. {
165.  assert(phead);
166. 
167.  ListNode* cur = phead->next;
168.  while (cur != phead)
169.  {
170.    ListNode* next = cur->next;
171.    free(cur);
172.    cur = next;
173.  }
174. 
175.  free(phead);
176. }

038-test.c

1. #define  _CRT_SECURE_NO_WARNINGS  1
2. #include "038-List.h"
3. #include<stdio.h>
4. #include<assert.h>
5. 
6. //带头结点
7. 
8. testList1() {
9.  ListNode* plist = ListInit();
10.   ListPushBack(plist, 1);
11.   ListPrint(plist);
12. 
13.   ListPushBack(plist, 1);
14.   ListPrint(plist);
15. 
16.   ListPushFront(plist, 2);
17.   ListPrint(plist);
18. 
19.   ListPushBack(plist, 3);
20.   ListPrint(plist);
21. 
22.   ListPopBack(plist);
23.   ListPrint(plist);
24. 
25.   ListPopFront(plist);
26.   ListPrint(plist);
27. 
28. 
29. 
30.   ListPushFront(plist, 4);
31.   ListPrint(plist);
32. 
33.   ListPushFront(plist, 5);
34.   ListPrint(plist);
35. 
36.   ListNode* pos = ListFind(plist, 5);
37.   ListInsert(pos, 100);
38.   ListErase(pos);
39.   ListPrint(plist);
40. 
41.   printf("%d", ListSize(plist));
42. 
43.   ListDestroy(plist);
44.   plist = NULL;
45. }
46. 
47. int main()
48. {
49.   testList1();
50.   return 0;
51. }


相关文章
|
4月前
|
算法 数据处理 C语言
C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合
本文深入解析了C语言中的位运算技巧,涵盖基本概念、应用场景、实用技巧及示例代码,并讨论了位运算的性能优势及其与其他数据结构和算法的结合,旨在帮助读者掌握这一高效的数据处理方法。
128 1
|
4月前
|
存储 算法 搜索推荐
【趣学C语言和数据结构100例】91-95
本文涵盖多个经典算法问题的C语言实现,包括堆排序、归并排序、从长整型变量中提取偶数位数、工人信息排序及无向图是否为树的判断。通过这些问题,读者可以深入了解排序算法、数据处理方法和图论基础知识,提升编程能力和算法理解。
88 4
|
4月前
|
存储 机器学习/深度学习 搜索推荐
【趣学C语言和数据结构100例】86-90
本文介绍并用C语言实现了五种经典排序算法:直接插入排序、折半插入排序、冒泡排序、快速排序和简单选择排序。每种算法都有其特点和适用场景,如直接插入排序适合小规模或基本有序的数据,快速排序则适用于大规模数据集,具有较高的效率。通过学习这些算法,读者可以加深对数据结构和算法设计的理解,提升解决实际问题的能力。
67 4
|
1月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》算法题基础篇—链表(下)
408考研——《数据结构》算法题基础篇之链表(下)。
95 29
|
1月前
|
定位技术 C语言
c语言及数据结构实现简单贪吃蛇小游戏
c语言及数据结构实现简单贪吃蛇小游戏
|
1月前
|
存储 算法 C语言
C 408—《数据结构》算法题基础篇—链表(上)
408考研——《数据结构》算法题基础篇之链表(上)。
107 25
|
2月前
|
搜索推荐 C语言
数据结构(C语言)之对归并排序的介绍与理解
归并排序是一种基于分治策略的排序算法,通过递归将数组不断分割为子数组,直到每个子数组仅剩一个元素,再逐步合并这些有序的子数组以得到最终的有序数组。递归版本中,每次分割区间为[left, mid]和[mid+1, right],确保每两个区间内数据有序后进行合并。非递归版本则通过逐步增加gap值(初始为1),先对单个元素排序,再逐步扩大到更大的区间进行合并,直至整个数组有序。归并排序的时间复杂度为O(n*logn),空间复杂度为O(n),且具有稳定性,适用于普通排序及大文件排序场景。
|
2月前
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】单链表的基本运算(头歌实践教学平台习题)【合集】
本内容介绍了单链表的基本运算任务,涵盖线性表的基本概念、初始化、销毁、判定是否为空表、求长度、输出、求元素值、按元素值查找、插入和删除数据元素等操作。通过C++代码示例详细解释了顺序表和链表的实现方法,并提供了测试说明、通 - **任务描述**:实现单链表的基本运算。 - **相关知识**:包括线性表的概念、初始化、销毁、判断空表、求长度、输出、求元素值、查找、插入和删除等操作。 - **测试说明**:平台会对你编写的代码进行测试,提供测试输入和预期输出。 - **通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了测试通过后的预期输出结果。 开始你的任务吧,祝你成功!
107 5
|
3月前
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
4月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
111 5