手把手写数据结构之单向循环链表操作

  1 /**************************头文件***************************/
  2 
  3 #ifndef _LINK_H_
  4 #define _LINK_H_
  5 
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8 #include <time.h>
  9 
 10 
 11 #define Test(arg)     if(arg == NULL){
 12         printf("Invalid arg!
");
 13         return -1;
 14     }
 15 
 16 /*单链表的实现可以各有不同,只要该实现,符合链表的定义即可。
 17  *单链表最重要的数据结构是元素结点,
 18  *最重要的操作是插入结点,删除结点和遍历。
 19  *其它的操作基本上是这3个操作的组合,依据具体的要求而定。
 20 */
 21 
 22 /*切记作为非空循环链表: 恒成立(tail->next == head)*/
 23 
 24 /*******************************************
 25 *单向循环链表结点信息
 26 *
 27 *数据域:    可以是普通类型,也可以是封装类型
 28 *指针域:    next指针
 29 *
 30 *********************************************/
 31 typedef struct node
 32 {
 33     int num;            //数据域
 34     struct node *next;    //指针域
 35 }NODE;
 36 
 37 /*******************************************
 38 *单向循环链表信息
 39 *
 40 *链表的属性信息: 链表的作用描述,链表当前节点个数等等
 41 *指针信息:        一般必须有表头指针,也可以有尾结点指针
 42 *
 43 *********************************************/
 44 typedef struct list_info
 45 {
 46     int max;            //结点个数
 47     NODE *head;            //头结点指针
 48     NODE *tail;            //尾结点指针
 49 }LIST_INFO;
 50 
 51 
 52 /*******************************************
 53 *Des:    单向循环链表初始化操作,即创建链表
 54 *Ret:    成功返回0,失败返回-1
 55 *********************************************/
 56 int Init_Link(LIST_INFO **plist);
 57 
 58 
 59 /*******************************************
 60 *Des:    判断链表是否为空
 61 *Ret:    真空返回1,假空返回0
 62 *********************************************/
 63 int IS_Empty_Link(LIST_INFO *plist);
 64 
 65 /*******************************************
 66 *Des:    清空链表
 67 *Ret:    成功返回0, 失败返回-1
 68 *********************************************/
 69 int Empty_Link(LIST_INFO *plist);
 70 
 71 /*******************************************
 72 *Des:    插入结点到表头(与在表尾操作类似)
 73 *Ret:    成功返回0,失败返回-1
 74 *********************************************/
 75 int Insert_to_Head(LIST_INFO *plist, int num);
 76 
 77 /*******************************************
 78 *Des:    删除数据域为num的结点
 79 *Ret:    成功返回0,失败返回-1
 80 *********************************************/
 81 int Delete_Node_Num(LIST_INFO *plist, int num);
 82 
 83 
 84 
 85 /*******************************************
 86 *Des:    销毁链表
 87 *Ret:    成功返回0,失败返回-1
 88 *********************************************/
 89 int Destory_Link(LIST_INFO **plist);
 90 
 91 /*******************************************
 92 *Des:    遍历链表
 93 *Ret:    成功返回0,失败返回-1
 94 *********************************************/
 95 int Traverse_Link(LIST_INFO *plist);
 96 
 97 #endif
 98 
 99 
100 
101 /*************************循环链表API接口函数实现*************************/
102 
103 
104 #include "sc_link.h"
105 
106 /*******************************************
107 *Des:    创建结点
108 *Ret:    成功返回结点,失败返回NULL
109 *********************************************/
110 static NODE *__Create_Node__(int num)
111 {
112     NODE *new_node = (NODE *)malloc(sizeof(NODE));
113     if(NULL == new_node)
114     {
115         perror("Create Node");
116         return NULL;
117     }
118 
119     new_node->next = NULL;
120     new_node->num = num;
121 
122     return new_node;
123 }
124 
125 
126 /*******************************************
127 *Des:    单向循环链表初始化操作,即创建链表
128 *Ret:    成功返回0,失败返回-1
129 *********************************************/
130 int Init_Link(LIST_INFO ** plist)
131 {
132     Test(plist);//参数有效性检测
133 
134     //创建链表
135     *plist = (LIST_INFO *)malloc(sizeof(LIST_INFO));
136     if(NULL == *plist)
137     {
138         perror("Create List");
139         return -1;
140     }
141 
142     //初始化链表
143     (*plist)->head = (*plist)->tail = NULL;
144     (*plist)->max = 0;
145 
146     return 0;
147 }
148 
149 /*******************************************
150 *Des:    判断链表是否为空
151 *Ret:    真空返回1,假空返回0
152 *********************************************/
153 int IS_Empty_Link(LIST_INFO *plist)
154 {
155     return (NULL == plist->head);
156 }
157 
158 /*******************************************
159 *Des:    清空链表
160 *Ret:    成功返回0, 失败返回-1
161 *********************************************/
162 int Empty_Link(LIST_INFO *plist)
163 {
164     Test(plist);//参数有效性检测
165 
166     //判断是否已经为空
167     if(IS_Empty_Link(plist))
168     {
169         printf("The list is empty!
");
170         return -1;
171     }
172 
173     NODE *fnode = NULL, *pnode = plist->head;
174     while(plist->tail != pnode)
175     {
176         fnode = pnode;
177         pnode = pnode->next;
178         free(fnode);
179     }
180     fnode = plist->tail;
181     free(fnode);
182 
183     plist->head = plist->tail = NULL;
184     plist->max = 0;
185     
186     return 0;
187 }
188 
189 /*******************************************
190 *Des:    销毁链表
191 *Ret:    成功返回0,失败返回-1
192 *********************************************/
193 int Destory_Link(LIST_INFO **plist) 
194 {
195     Test(plist);//函数入口检测
196 
197     //清空链表
198     if(Empty_Link(*plist) < 0)
199         return -1;
200 
201     free(*plist);
202 
203     *plist = NULL;
204 
205     return 0;
206 }
207 
208 
209 
210 /*******************************************
211 *Des:    插入结点到表头(与在表尾操作类似)
212 *Ret:    成功返回0,失败返回-1
213 *********************************************/
214 int Insert_to_Head(LIST_INFO *plist, int num)
215 {
216     Test(plist);//参数有效性检测
217 
218     NODE *new_node = __Create_Node__(num);
219     if(NULL == new_node)
220         return -1;
221 
222     if(IS_Empty_Link(plist))//当链表为空
223     {
224         plist->head = plist->tail = new_node;
225         plist->head->next = plist->tail;
226         plist->tail->next = plist->head;
227     }
228     else
229     {
230         plist->tail->next = new_node;
231         new_node->next = plist->head;
232         plist->head = new_node;
233     }
234 
235     plist->max++;
236 
237     return 0;
238 }
239 
240 /*******************************************
241 *Des:    删除数据域为num的结点
242 *Ret:    成功返回0,失败返回-1
243 *********************************************/
244 int Delete_Node_Num(LIST_INFO *plist, int num)
245 {
246     Test(plist);
247 
248     NODE *fnode = NULL, *tmpnode = NULL, *pnode = NULL;
249 
250     //判断链表是否为空
251     if(IS_Empty_Link(plist))
252     {
253         printf("The list is empty!
");
254         return -1;
255     }
256 
257     //查找结点是否有符合的
258     pnode = plist->head;
259     while(pnode != plist->tail)
260     {
261         if(pnode->num == num)
262             break;
263         tmpnode = pnode;
264         pnode = pnode->next;
265     }
266     if(pnode == plist->tail)//结束条件为到了链表的尽头
267     {
268         if(pnode->num == num)//如果尾结点是的
269         {
270             fnode = pnode;
271             if(plist->max == 1)//只有一个节点
272             {
273                 plist->head = plist->tail = NULL;
274             }
275             else
276             {
277                 tmpnode->next = plist->head;
278                 plist->tail = tmpnode;
279             }
280         }
281         else
282         {
283             printf("Have no such Node!
");
284             return -1;
285         }
286     }
287     else//循环条件因为找到符合的结点而结束的
288     {
289         if(NULL == tmpnode)//如果是头结点
290         {
291             fnode = plist->head;
292             plist->tail->next = fnode->next;
293             plist->head = fnode->next;
294         }
295         else
296         {
297             fnode = tmpnode->next;
298             tmpnode->next = fnode->next;
299         }
300     }
301 
302     free(fnode);
303     plist->max--;
304 
305     return 0;
306 }
307 
308 /*******************************************
309 *Des:    遍历链表
310 *Ret:    成功返回0,失败返回-1
311 *********************************************/
312 int Traverse_Link(LIST_INFO *plist)
313 {
314     Test(plist);//参数有效性检测
315     
316     if(IS_Empty_Link(plist))//判断链表是否为空
317     {
318         printf("The list is empty!
");
319         return -1;
320     }
321 
322     printf("The count of Node: %d
", plist->max);
323     NODE *pnode = plist->head;
324     while(pnode != plist->tail)
325     {
326         printf("%-5d", pnode->num);
327         pnode =pnode->next;
328     }
329     printf("%-5d", pnode->num);
330 
331     printf("

");
332 
333     return 0;
334 }
335 
336 
337 
338 /**************************测试代码***************************/
339 
340 #include "sc_link.h"
341 #define RANDOM rand()%10
342 
343 int main()
344 {
345 
346     srand(time(NULL));
347     
348     int i, num;
349     LIST_INFO *plist = NULL;
350 
351     //初始化链表操作
352     Init_Link(&plist);
353 
354     //添加结点
355     //for(i = 0; i < 5; i++)
356     //{
357     //    num = RANDOM;
358     //    printf("%5d", num);
359         Insert_to_Head(plist, 8);
360     //}
361     printf("

");
362 
363     Traverse_Link(plist);
364 
365     //清空链表操作
366     //Empty_Link(plist);
367 
368     Delete_Node_Num(plist, 8);
369 
370     Traverse_Link(plist);
371 
372     return 0;
373 }
原文地址:https://www.cnblogs.com/xuyh/p/3232671.html