不帶頭結點的單鏈表------C語言實現


  1 /****************************************************/  3 File name:no_head_link.c
  4 Author:SimonKly   Version:0.1    Date: 2017.5.20
  5 Description:不帶頭節點的單鏈表
  6 Funcion List: 
  7 *****************************************************/
  8 
  9 #include <stdio.h>
 10 #include <stdlib.h>
 11 
 12 typedef struct node
 13 {
 14     int id;
 15     struct node * next;
 16 }* Link, Node;
 17 
 18 /*創建鏈表*/
 19 void create_link(Link * head)
 20 {
 21     *head = NULL;//空鏈表
 22 }
 23 
 24 /*頭插*/
 25 void insert_node_head(Link * head, Link new_node)
 26 {
 27     new_node->next = *head;
 28     *head = new_node;
 29 }
 30 
 31 #if 1
 32 /*尾插*/
 33 void insert_node_tail(Link * head, Link new_node)
 34 {
 35     Link p = NULL;
 36 
 37     if (*head == NULL)
 38     {
 39         *head =new_node;
 40         new_node->next = NULL;
 41         return ;
 42     }
 43     else
 44     {
 45         p = *head;
 46         while (p->next != NULL)
 47         {
 48             p = p->next;
 49         }
 50         p->next = new_node;
 51         new_node->next = NULL;
 52     }
 53 }
 54 #endif
 55 
 56 /*輸出鏈表*/
 57 void display_link(Link head)
 58 {
 59     Link p = NULL;
 60 
 61     p = head;
 62 
 63     if(p == NULL)
 64     {
 65         printf("link is empty!\n");
 66         return ;
 67     }
 68 
 69     while (p != NULL)
 70     {
 71         printf("id = %d\n", p->id);
 72         p = p->next;
 73     }
 74 
 75     putchar(10);
 76 }
 77 
 78 /*檢查malloc是否分配成功*/
 79 void is_malloc_ok(Link new_node)
 80 {
 81     if (new_node == NULL)
 82     {
 83         printf("malloc error!\n");
 84         exit(-1);
 85     }
 86 }
 87 
 88 /*創建節點*/
 89 void create_node(Link * new_node)
 90 {
 91     *new_node = (Link)malloc(sizeof(Node));
 92 
 93     is_malloc_ok(*new_node);
 94 }
 95 
 96 /*釋放節點*/
 97 void realse_node(Link * head)
 98 {
 99     Link p = NULL;
100 
101     p = *head;
102     while (*head != NULL)
103     {
104         *head = (*head)->next;//head移動
105         free(p);//釋放head之前的節點
106         p = *head;
107     }
108 }
109 
110 
111 /*中間插入節點*/
112 void insert_node_mid(Link * head, Link new_node, int loc)
113 {
114     int i;
115     Link p = NULL;
116 
117     p = *head;
118 
119     for(i = 1; i < loc; i++)
120     {
121         p = p->next;
122     }
123 
124     new_node->next = p->next;
125     p->next = new_node;
126 }
127 
128 /*中間插入,前面*/
129 void insert_node_mid_front(Link * head, Link new_node)
130 {
131     Link p = NULL, q = NULL;
132 
133     p = q = *head;
134 
135     if (*head == NULL)
136     {
137         printf("link is empty\n");
138         return ;
139     }
140 
141     while (p != NULL && p->id != new_node->id)
142     {
143         q = p;
144         p = p->next;
145     }
146     
147     if (p == NULL)
148     {
149         printf("No such node in link!\n");
150         free(new_node);
151         return ;
152     }
153     if (p->id == (*head)->id)
154     {
155         new_node->next = *head;
156         *head = new_node;
157     }
158     else
159     {
160         q->next = new_node;
161         new_node->next = p;
162     }
163 }
164 #if 1
165 /*刪除節點*/
166 void delete_node(Link * head, int data)
167 {
168     Link p = NULL, q = NULL;
169 
170     q = p = *head;
171 
172     if (p == NULL)//鏈表為空的時候
173     {
174         printf("link is empty!\n");
175         return ;
176     }
177     else//鏈表不為空的時候
178     {
179         while (p != NULL && p->id != data)//尋找節點
180         {
181             q = p;
182             p = p->next;
183         }
184 
185         if ((*head)->id == data)//刪除節點為頭節點時
186         {
187             *head = (*head)->next;
188             free(p);//free(q);
189         }
190         else//刪除節點不為頭節點,尾節點不用考慮
191         {
192             q->next = p->next;
193             free(p);
194         }
195     }
196 }
197 #endif
198 
199 #if 0
200 void delete_node(Link * head, int data)
201 {
202     Link p = NULL, q = NULL;
203 
204     q = p = *head;
205 
206     if (p == NULL)//鏈表為空的時候
207     {
208         printf("link is empty!\n");
209         return ;
210     }
211     else//鏈表不為空的時候
212     {
213         while (p != NULL && (p->next)->id != data)//尋找節點
214         {
215             p = p->next;
216         }
217 
218         if ((*head)->id == data)//刪除節點為頭節點時
219         {
220             *head = (*head)->next;
221             free(p);//free(q);
222         }
223         else//刪除節點不為頭節點,尾節點不用考慮
224         {
225             q = p->next;
226             p->next = q->next;
227             free(q);
228         }
229     }
230 }
231 #endif
232 
233 /*插入之后依舊有序*/
234 void insert_node_seq(Link * head, Link new_node)
235 {
236     Link p = NULL, q = NULL;
237 
238     p = q = *head;
239 
240     if (p == NULL)//鏈表為空的時候
241     {
242         *head = new_node;
243         new_node->next = NULL;
244     }
245     else
246     {
247         while (p != NULL && p->id < new_node->id)//尋找位置
248         {
249             q = p;
250             p = p->next;
251         }
252         
253         if ((*head)->id > new_node->id)//找到的節點為頭節點
254         {
255             new_node->next = *head;
256             *head = new_node;
257         }
258         else
259         {
260             q->next = new_node;
261             new_node->next = p;
262         }
263     }
264 }
265 
266 #if 1
267 /*插入依舊有序實現方法二*/
268 void insert_node_seq_1(Link * head, Link new_node)
269 {
270     Link p = NULL;
271     Link q = NULL;
272 
273     p = q = *head;
274 
275     if (p == NULL)//空鏈表
276     {
277         *head = new_node;
278         new_node->next =NULL;
279     }
280     else
281     {
282         while ((p->id < new_node->id) && (p->next != NULL))
283         {
284             q = p;
285             p = p->next;
286         }
287         
288         if ((*head)->next == NULL)//一個節點的時候
289         {
290             if (p->id > new_node->id)
291             {
292                 new_node->next = *head;
293                 *head = new_node;
294             }
295             else
296             {
297                 p->next = new_node;
298             }
299         }
300         else
301         {
302             if (p->next == NULL)//尾節點
303             {
304                 if (p->id > new_node->id)//插入前
305                 {
306                     q->next = new_node;
307                     new_node->next = p;
308                 }
309                 else
310                 {
311                     p->next = new_node;
312                 }
313             }
314             else//不是尾節點
315             {
316                 if((*head)->id > new_node->id)//頭節點
317                 {
318                     new_node->next = *head;
319                     *head = new_node;
320                 }
321                 else//中間插入時
322                 {
323                     q->next = new_node;
324                     new_node->next = p;
325                 }
326             }
327         }/*end of if()*/
328     }/*end of if (p == NULL)*/
329 }
330 #endif
331 
332 int main()
333 {
334     Link head = NULL;//防止出現野指針
335     Link new_node = NULL;//防止出現野指針
336     int i;
337     int data;
338 
339     create_link(&head);//創建鏈表
340 
341     for (i = 0; i < 10; i++)//值域賦值,並插入新節點
342     {
343     //    new_node = (Link)malloc(sizeof(Node));//創建新節點
344         create_node(&new_node);
345     //    new_node->id = i + 1;//賦值
346     //    insert_node_head(&head, new_node);//插入節點,頭插
347     //    insert_node_tail(&head, new_node);//插入節點,尾插
348     
349         printf("please input node value:\n");
350         scanf("%d", &new_node->id);
351         insert_node_seq(&head, new_node);
352 //        insert_node_seq_1(&head, new_node);
353         display_link(head);//輸出節點的值域
354     }
355 
356     display_link(head);//輸出節點的值域
357 
358 #if 0
359     create_node(&new_node);
360     new_node->id = i + 1;
361     insert_node_mid(&head, new_node, 3);//指定位置插入,中間插入
362     putchar(10);
363     display_link(head);//輸出節點的值域
364 
365 #if 0
366     create_node(&new_node);
367     scanf("%d", &new_node->id);
368     insert_node_mid_front(&head, new_node);
369     display_link(head);//輸出節點的值域
370 #endif
371 
372     scanf("%d", &i);
373     delete_node(&head, i);//刪除指定節點
374     display_link(head);
375 
376 #if 0
377 
378     create_node(&new_node);
379     scanf("%d", &new_node->id);
380     insert_node_seq(&head, new_node);//有序插入指定元素
381     display_link(head);
382 #endif
383 #endif
384     realse_node(&head);//釋放節點
385 
386     display_link(head);//輸出節點的值域
387     return 0;
388 }

由於鏈式數據結構中有指針的各種指向問題,所以在紙上畫圖是比較容易理解。

其中在對頭指針(注意是頭指針,不是頭節點,兩個不是一個概念,頭指針是整個鏈表的操作的基礎,鏈表存在的象征,頭指針是整個“鏈表公司”的一把手,頭頭結點是鏈表中的第一個元素)的操作,除了在插入,刪除和銷毀中頭指針的指向發生改變,需要直接對頭指針head操作外,其他方法都不要對頭指針進行操作,以免丟失整個鏈表。

在對鏈表中的增加時,需要考慮鏈表中開始存在的元老級的“人物”,所以我們不能隨便就對它們變換“崗位”,我得先找到”接班人“之后再對這些元老級的崗位進行調整。

在對鏈表中的節點進行刪除時,也需要首先考慮這些元老級的“人物”,畢竟人家沒有功勞也有苦勞,我們得代理好它走后它的”上級“和他的”下級“溝通交流的問題。

代碼中的一些條件編譯和注釋是未完成一些功能的另一種方法。

在銷毀整個鏈表時,相當於整個鏈表公司破產,作為公司一把手的head,依次需要對手下任勞任怨的員工進行思想工作。當整個公司沒有員工時,一把手也什么都沒有了即NULL。

代碼中的功能函數包括:

1.創建鏈表

2.創建節點

3.插入節點------------頭插,尾插以及插入即有序,指定位置插入的方法,根據需要選擇合適的方法

  頭插:實現鏈式棧

  尾插:實現鏈式隊列

4.刪除節點

5.銷毀整個鏈

6.判斷malloc函數是否執行成功

7.輸出鏈

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM