线性表分为顺序表和链表,前面说过顺序表,这里说链表。
链表:一种链式存储的线性表,用一组地址任意的存储单元存放线性表的数据元素,称存储单元为一个结点。
链表分类从三个方面来分:
- 单向链表、双向链表
- 带环链表、不带环链表
- 带头结点链表、不带头结点链表
下面实现一些 单向不带环无头结点链表的基本操作:
// 头文件
3 #include<stdio.h>
4 #include<stdlib.h>
5 #include<string.h>
6 #include <stddef.h>
// 自定义类型
7
8 typedef char LinkListType;
9
10 typedef struct LinkList{
11 LinkListType data;
12 struct LinkList* next;
13 }LinkList;
1. 创建链表结点
4 LinkList* CreatNode(LinkListType value)
5 {
6 LinkList* new_node = (LinkList*)malloc(sizeof(LinkList));
7 new_node->data = value;
8 new_node->next = NULL;
9 return new_node;
10 }
2.
销毁链表结点
12 void DestoryNode(LinkList* node)
13 {
14 if(node){
15 free(node);
16 }
17 return;
18 }
3. 链表初始化
20 void LinkListInit(LinkList** head)
21 {
22 if(head == NULL){
23 // 非法输入
24 return;
25 }
26 *head = NULL;
27 }
4. 尾插
29 void LinkListPushBack(LinkList** head, LinkListType value)
30 {
31 if(head == NULL){
32 // 非法输入
33 return ;
34 }
35 if(*head == NULL){
36 // 空链表,新结点为头结点
37 *head = CreatNode(value);
38 return;
39 }
40 LinkList* cur = *head;
41 while(cur->next != NULL){ // 找到最后一个结点,插入新结点
42 cur = cur->next;
43 }
44 cur->next = CreatNode(value);
45 return;
46 }
5. 尾删
48 void LinkListPopBack(LinkList** head)
49 {
50 if(head == NULL){
51 // 非法输入
52 return ;
53 }
54 if(*head == NULL){
55 // 空链表
56 return;
57 }
58 LinkList* cur = *head;
59 if(cur->next == NULL){
60 DestoryNode(cur);
61 (*head) = NULL;
62 }
63 while(cur->next != NULL){ // cur 的下一个结点不为空,才能解引用
64 if(cur->next->next == NULL){
65 break;
66 }
67 cur = cur->next;
68 }
69 LinkList* to_delete = cur->next;
70 cur->next = NULL;
71 DestoryNode(to_delete);
72 }
6. 头插
74 void LinkListPushFront(LinkList** head, LinkListType value)
75 {
76 if(head == NULL){
77 // 非法输入
78 return ;
79 }
80 if(*head == NULL){
81 // 空链表
82 (*head) = CreatNode(value);
83 return;
84 }
85 LinkList* new_node = CreatNode(value);
86 new_node->next = *head;
87 *head = new_node;
88 }
7. 头删
90 void LinkListPopFront(LinkList** head)
91 {
92 if(head == NULL){
93 // 非法输入
94 return ;
95 }
96 if(*head == NULL){
97 // 空链表
98 return;
99 }
100 LinkList* to_delete = (*head);
101 *head = (*head)->next;
102 return;
103 }
8. 查找 find 值,并返回位置
105 LinkList* LinkListFind(LinkList* head, LinkListType to_find)
106 {
107 if(head == NULL){
108 // 空链表
109 return NULL;
110 }
111 LinkList* cur = head;
112 while(cur != NULL){
113 if(cur->data == to_find){
114 return cur;
115 }
116 cur = cur->next;
117 }
118 return NULL;
119 }
9. 在 pos 位置之前插入新结点(遍历链表)
122 void LinkListPosInsert(LinkList** head, LinkList* pos, LinkListType value)
123 {
124 if(head == NULL || pos == NULL){
125 // 非法输入
126 return;
127 }
128 if(*head == NULL){
129 return;
130 }
131 if(pos == *head){
132 LinkList* new_node = CreatNode(value);
133 new_node->next = *head;
134 *head = new_node;
135 return;
136 }
137 LinkList* new_node = CreatNode(value);
138 LinkList* cur = *head;
139 while(cur){
140 if(cur->next == pos){
141 break;
142 }
143 cur = cur->next;
144 }
145 new_node->next = cur->next;
146 cur->next = new_node;
147 return;
148 }
10. 在 pos 位置之前插入新结点(不遍历链表)
150 void LinkListPosInsert2(LinkList** head, LinkList* pos, LinkListType value)
151 {
152 if(head == NULL || pos == NULL){
153 // 非法输入
154 return;
155 }
156 if(*head == NULL){
157 return;
158 }
159 if(pos == *head){
160 LinkList* new_node = CreatNode(value);
161 new_node->next = *head;
162 *head = new_node;
163 return;
164 }
165 LinkList* new_node = CreatNode(value); // 不遍历链表,在 pos 之后插入,交换 pos 和 new_node 的值
166 new_node->next = pos->next;
167 pos->next = new_node;
168 new_node->data = pos->data;
169 pos->data = value;
170 return;
171 }
11. 在 pos 位置之后插入新结点
173 void LinkListAfterPosInsert(LinkList* pos, LinkListType value)
174 {
175 if(pos == NULL){
176 // 非法输入
177 return;
178 }
179 LinkList* new_node = CreatNode(value);
180 new_node->next = pos->next;
181 pos->next = new_node;
182 return;
183 }
12. 删除 pos 位置的结点
185 void LinkListEraser(LinkList** head, LinkList* pos)
186 {
187 if(head == NULL || pos == NULL){
188 // 非法输入
189 return;
190 }
191 if(*head == NULL){
192 // 空链表
193 return;
194 }
195 if(*head == pos){
196 (*head) = (*head)->next;
197 DestoryNode(pos);
198 return;
199 }
200 LinkList* cur = *head;
201 while(cur->next != NULL){
202 if(cur->next != pos){
203 cur = cur->next;
204 continue;
205 }
206 cur->next = pos->next;
207 DestoryNode(pos);
208 }
209 // 没有找到pos
210 return;
211 }
13. 删除指定值的结点(第一个,只删一次)
213 void LinkListRemove(LinkList** head, LinkListType to_delete)
214 {
215 if(head == NULL){
216 // 非法输入
217 return;
218 }
219 if(*head == NULL){
220 // 空链表
221 return;
222 }
223 if((*head)->data == to_delete){
224 LinkList* to_delete = *head;
225 (*head) = (*head)->next;
226 DestoryNode(to_delete);
227 return;
228 }
229 LinkList* cur = *head;
230 while(cur->next != NULL){
231 if(cur->next->data != to_delete){
232 cur = cur->next;
233 continue;
234 }
235 LinkList* to_delete = cur->next;
236 cur->next = to_delete->next;
237 DestoryNode(to_delete);
238 break;
239 }
240 return;
241 }
14. 删除指定值的所有结点
243 void LinkListRemoveAll(LinkList** head, LinkListType value)
244 {
245 if(head == NULL){
246 //非法输入
247 return;
248 }
249 if(*head == NULL){
250 // 空链表
251 return;
252 }
253 while((*head)->data == value){
254 LinkList*to_delete = *head;
255 (*head) = (*head)->next;
256 DestoryNode(to_delete);
257 }
258 LinkList* cur = *head;
259 while(cur->next != NULL){
260 if(cur->next->data != value){
261 cur = cur->next;
262 continue;
263 }
264 LinkList* to_delete = cur->next;
265 cur->next = to_delete->next;
266 DestoryNode(to_delete);
267 }
268 return;
269 }
15. 计算链表元素个数,并返回个数
271 size_t LinkListSize(LinkList* head)
272 {
273 if(head == NULL){
274 return 0;
275 }
276 size_t count = 0;
277 LinkList* cur = head;
278 while(cur != NULL){
279 cur = cur->next;
280 count++;
281 }
282 return count;
283 }
16. 销毁链表
285 void DestroyList(LinkList** head)
286 {
287 if(head == NULL){
288 return;
289 }
290 if(*head == NULL){
291 return;
292 }
293 LinkList* to_delete = *head;
294 LinkList* next = to_delete->next;
295 while(next != NULL){
296 DestoryNode(to_delete);
297 to_delete = next;
298 next = to_delete->next;
299 }
300 DestoryNode(to_delete);
301 *head = NULL;
302 return;
303 }