不带头结点的单链表------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.输出链

 

posted @ 2017-05-22 17:00  SimonKly  阅读(7186)  评论(1编辑  收藏  举报