si-lei

C语言实现单链表,并完成链表常用API函数:

  1.链表增、删、改、查。

  2.打印链表、反转打印、打印环形链表。

  3.链表排序、链表冒泡排序、链表快速排序。

  4.求链表节点个数(普通方法、递归方法)。

  5.链表反转(普通方法、递归方法)。

  6.链表合并。

  7.获取链表中间节点。

  8.判断链表是否有环。

 

LinkList.h :

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 
 4 struct LinkNode
 5 {
 6     int data;
 7     struct LinkNode *pNext;
 8 };
 9 
10 typedef struct LinkNode Node;    //简化类型
11 
12 void init(Node *phead);                            //初始化
13 Node *addBack(Node *phead, int data);            //尾插法:尾部添加节点
14 void addHead(Node *phead, int data);            //头插法:头部添加节点
15 
16 void ShowAll(Node *phead);                        //显示链表
17 void revShowAll(Node *phead);                    //反转显示链表                                
18 void ShowCircleLink(Node *phead);                //显示环形链表
19 
20 Node *searchFirst(Node *phead, int findData);    //查找
21 
22 Node *changeFirst(Node *phead, int findData, int newData);    //修改
23 
24 Node *delFirst(Node *phead, int delData);        //删除
25 
26 Node *insertFirst(Node *phead, int insertData,int newData);        //插入
27 
28 void bubbleSort(Node *phead);                    //冒泡排序
29 
30 void quickSort(Node *pbegin, Node *pback);        //快速排序法:(双冒泡)
31 Node *fen(Node *pbegin, Node *pback);            //分段
32 
33 int getNum1(Node *phead);                        //求链表节点个数
34 int getNum2(Node *phead);                        //求链表节点个数(递归)
35 
36 Node *revList1(Node *phead);                    //链表反转(普通方法)
37 Node *revList2(Node *phead);                    //链表反转(递归方法)
38 
39 //将链表phead1和phead2合并到phead3,并返回链表phead3
40 Node *mergeList(Node *phead3, Node *phead1, Node *phead2);        //链表合并
41 
42 Node *getMid(Node *phead);                        //获取链表的中间节点
43 
44 int judgeCircle(Node *phead);                    //判断链表是否有环

LinkList.c :

  1 #include "LinkList.h"
  2 
  3 //初始化
  4 void init(Node *phead)
  5 {
  6     phead->pNext = NULL;
  7     phead->data = 0;
  8 }
  9 
 10 //显示链表
 11 void ShowAll(Node *phead)
 12 {
 13     if (phead == NULL)
 14         return;
 15     else
 16     {
 17         printf("%4d", phead->data);
 18         //printf("%d,%p,%p\n", phead->data, phead, phead->pNext);
 19         ShowAll(phead->pNext);                                    //跳到下一个节点
 20 
 21     }
 22 }
 23 
 24 //反转显示链表
 25 void revShowAll(Node *phead)
 26 {
 27     if (phead == NULL)
 28         return;
 29     else
 30     {
 31         printf("%d,%p,%p\n", phead->data, phead, phead->pNext);
 32         ShowAll(phead->pNext);                                    //跳到下一个节点
 33 
 34     }
 35 }
 36 
 37 //显示环形链表
 38 void ShowCircleLink(Node *phead)
 39 {
 40     if (phead == NULL)
 41         return;
 42     else
 43     {
 44         Node *p = phead;
 45         for (; p->pNext != phead; p = p->pNext)
 46             printf("%4d", p->data);
 47 
 48         printf("%4d", p->data);    //还需要再打印最后一个元素
 49 
 50     }
 51 }
 52 
 53 //尾插法:尾部添加节点  (改变了头指针,改变一个指针,要么二级指针,要么用返回值给指针赋值,这里采用返回值)
 54 Node *addBack(Node *phead, int data)
 55 {
 56     Node *pnew = malloc(sizeof(Node));    //构建新的节点
 57     pnew->data = data;                    //新节点赋值
 58     pnew->pNext = NULL;
 59 
 60     if (phead == NULL)                    //phead为空,直接连接
 61         phead = pnew;
 62     else
 63     {
 64         Node *ptemp = phead;            //备份一下头指针
 65         while (ptemp->pNext != NULL)
 66         {
 67             ptemp = ptemp -> pNext;        //循环前进
 68         }
 69         ptemp->pNext = pnew;            //链接
 70     }
 71 
 72     return phead;
 73 }
 74 
 75 //头插法:头部添加节点 (采用二级指针的方法)
 76 void addHead(Node **pphead, int data)
 77 {
 78     Node *pnew = malloc(sizeof(Node));    //构建新的节点
 79     pnew->data = data;                    //新节点赋值
 80     pnew->pNext = NULL;
 81 
 82     if(*pphead==NULL)
 83         pphead = pnew;
 84     else
 85     {
 86         pnew->pNext = *pphead;
 87         *pphead = pnew;
 88     }
 89 }
 90 
 91 //查找
 92 Node *searchFirst(Node *phead, int findData)
 93 {
 94     for (Node *p = phead; p != NULL; p = p->pNext)
 95     {
 96         if (p->data == findData)
 97         {
 98             return p;        //返回找到的指针位置
 99         }
100     }
101 
102     return NULL;
103 }
104 
105 //修改
106 Node *changeFirst(Node *phead, int findData, int newData)
107 {
108     for (Node *p = phead; p != NULL; p = p->pNext)
109     {
110         if (p->data == findData)
111         {
112             p->data = newData;
113             return p;        //返回找到的指针位置
114         }
115     }
116 
117     return NULL;
118 }
119 
120 //删除
121 Node *delFirst(Node *phead, int delData)
122 {
123     Node *p1=NULL, *p2=NULL;        //此时需要双指针
124     p1 = phead;            //保存头结点
125 
126     while (p1 != NULL)
127     {
128         if (p1->data != delData)
129         {
130             p2 = p1;        //p2保存的是p1的上一个位置
131             p1 = p1->pNext;
132         }
133         else
134             break;
135     }
136 
137     if (p1 != phead)
138     {
139         p2->pNext = p1->pNext;    //跳过p1
140         free(p1);                //删除p1
141     }
142     else
143     {
144         phead = phead->pNext;
145         free(p1);                //头部删除
146     }
147 
148     return phead;
149 }
150 
151 //插入
152 Node *insertFirst(Node *phead, int insertData, int newData)
153 {
154     Node *p1 = NULL, *p2 = NULL;        //此时需要双指针
155     p1 = phead;            //保存头结点
156 
157     while (p1 != NULL)
158     {
159         if (p1->data != insertData)
160         {
161             p2 = p1;        //p2保存的是p1的上一个位置
162             p1 = p1->pNext;    //向前移动
163         }
164         else
165             break;
166     }
167 
168     Node *pnew = malloc(sizeof(Node));    //构建新的节点
169     pnew->data = newData;                //新节点赋值
170     pnew->pNext = NULL;
171 
172     if (phead == p1)
173     {
174         pnew->pNext = phead;    //保存头结点
175         phead = pnew;            //头部插入
176     }
177     else
178     {
179         pnew->pNext = p1;
180         p2->pNext = pnew;        //插入
181     }
182 
183     return phead;
184 }
185 
186 //冒泡排序
187 void bubbleSort(Node *phead)
188 {
189     //数组可以随机访问任何一个元素,可以规避一些比较
190     //链表找到N个元素,必须先遍历N-1个元素
191     for (Node *p1 = phead; p1 != NULL; p1 = p1->pNext)
192     {
193         for (Node *p2 = phead; p2 != NULL; p2 = p2->pNext)
194         {
195             if (p1->data < p2->data)
196             {
197                 int temp;
198                 temp = p1->data;
199                 p1->data = p2->data;
200                 p2->data = temp;
201             }
202         }
203     }
204 }
205 
206 Node *fen(Node *pbegin, Node *pback)
207 {
208     int key = pbegin->data;        //以第一个数据为分段
209 
210     Node *p = pbegin;            //第一个节点
211     Node *q = pbegin->pNext;    //第二个节点
212 
213     while (q != pback)
214     {
215         if (q->data < key)
216         {
217             p = p->pNext;        //循环下一个节点
218 
219             int temp = p->data;    //交换
220             p->data = q->data;
221             q->data = temp;
222         }
223         q = q->pNext;            //循环第二个指针
224 
225         printf("\n枢轴为:(%d)", key);
226         printf("\n此时数:");
227         ShowAll(pbegin);
228 
229     }
230 
231     int temp = p->data;    //交换
232     p->data = pbegin->data;
233     pbegin->data = temp;
234 
235     printf("\n\n交换值:");
236     ShowAll(pbegin);
237     printf("\n-----------------------------------------------");
238 
239     return p;
240 }
241 
242 //快速排序法:(双冒泡)
243 void quickSort(Node *pbegin,Node *pback)
244 {
245     if (pbegin != pback)
246     {
247         Node *pfen = fen(pbegin, pback);    //取中间点,分成两段分别再进行快排
248 
249         quickSort(pbegin, pfen);            //前半段快排
250         quickSort(pfen->pNext, pback);        //后半段快排
251     }
252 }
253 
254 //求链表节点个数(普通方法)
255 int getNum1(Node *phead)
256 {
257     int i = 0;
258     for (; phead != NULL; phead = phead->pNext)
259     {
260         i++;
261     }
262     return i;
263 }
264 
265 //求链表节点个数(递归)
266 int getNum2(Node *phead)
267 {
268     if (phead == NULL)
269         return 0;
270     else
271         return 1 + getNum2(phead->pNext);
272 }
273 
274 //链表反转(普通方法)
275 Node *revList1(Node *phead)
276 {
277     if (phead == NULL || phead->pNext == NULL)
278         return phead;
279     else
280     {
281         Node *pre = NULL;
282         Node *pcur = NULL;
283         Node *pnext = NULL;
284 
285         pre = phead;
286         pcur = phead->pNext;
287         while (pcur != NULL)
288         {
289             pnext = pcur->pNext;    //备份下一个节点
290             pcur->pNext = pre;        //第一个节点指向NULL,此时pre指向NULL(指针反转)
291             
292             pre = pcur;                //前进
293             pcur = pnext;            //轮替前进
294         }
295 
296         phead->pNext = NULL;        //注意尾节点置空
297         phead = pre;
298     }
299 
300     return phead;
301 }
302 
303 //链表反转(递归方法)
304 Node *revList2(Node *phead)
305 {
306     if (phead == NULL || phead->pNext == NULL)
307         return phead;
308     else
309     {
310         Node *pnext = phead->pNext;        //顺序
311 
312         Node *Head = revList2(pnext);    //轮询所有的节点,递归调用
313 
314         pnext->pNext = phead;
315 
316         phead->pNext = NULL;            //逆序
317 
318         return Head; 
319     }
320 }
321 
322 //链表合并
323 Node *mergeList(Node *phead3, Node *phead1, Node *phead2)
324 {
325     Node *pcur1 = phead1;
326     Node *pcur2 = phead2;
327 
328     while (pcur1 != NULL || pcur2 != NULL)
329     {
330         if (pcur1 != NULL && pcur2 != NULL)
331         {
332             if (pcur1->data < pcur2->data)
333             {
334                 phead3 = addBack(phead3, pcur1->data);
335                 pcur1 = pcur1->pNext;
336             }
337             else
338             {
339                 phead3 = addBack(phead3, pcur2->data);
340                 pcur2 = pcur2->pNext;
341             }
342         }
343         else
344         {
345             while (pcur1 != NULL)
346             {
347                 phead3 = addBack(phead3, pcur1->data);
348                 pcur1 = pcur1->pNext;
349             }
350             while (pcur2 != NULL)
351             {
352                 phead3 = addBack(phead3, pcur2->data);
353                 pcur2 = pcur2->pNext;
354             }
355 
356             break;
357         }
358     }
359 
360     return phead3;
361 }
362 
363 //获取链表的中间节点
364 Node *getMid(Node *phead)
365 {
366     if (phead == NULL || phead->pNext == NULL)
367         return phead;
368     else
369     {
370         Node *p1 = phead;            //一次前进一步
371         Node *p2 = phead;            //一次前进两步
372 
373         while (p2->pNext != NULL)    //注意循环条件,而不是p2 != NULL
374         {
375             p1 = p1->pNext;
376             p2 = p2->pNext;
377             if (p2->pNext != NULL)
378                 p2 = p2->pNext;
379         }
380 
381         return p1;
382     }
383 }
384 
385 //判断链表是否有环
386 int judgeCircle(Node *phead)
387 {
388     int flag = 0;
389     for (Node *p1 = phead, *p2 = phead; p1 != NULL && p2 != NULL; p1 = p1->pNext, p2 = p2->pNext)    //死循环
390     {    
391         if(p2->pNext!=NULL)    //p2一次前进两步,而p1一次前进一步
392             p2 = p2->pNext;
393 
394         if (p1 == p2)
395         {
396             flag == 1;        //p1追上了p2,有环
397             break;
398         }
399             
400         
401     }
402 
403     return flag;
404 }

main.c :

  1 #include "LinkList.h"
  2 
  3 void main()
  4 {
  5     Node *phead = NULL;
  6     //init(phead);    //初始化,头结点不分配内存,这里不能初始化头结点
  7 
  8     phead = addBack(phead, 14);        //尾插
  9     phead = addBack(phead, 15);
 10     phead = addBack(phead, 16);
 11     phead = addBack(phead, 8);
 12     phead = addBack(phead, 12);
 13     phead = addBack(phead, 13);
 14 
 15     //addHead(&phead, 9);            //头插
 16     //addHead(&phead, 22);
 17     //addHead(&phead, 41);
 18     //addHead(&phead, 18);
 19     //ShowAll(phead);
 20 
 21     //Node *pfind = searchFirst(phead, 13);
 22     //pfind->data = 33;
 23     //ShowAll(phead);
 24 
 25     //Node *pchange = changeFirst(phead, 14,93);
 26     //ShowAll(phead);
 27 
 28     //ShowAll(phead);
 29     //printf("\n\n");
 30     //phead = delFirst(phead, 24);
 31     //ShowAll(phead);
 32 
 33     //printf("\n\n");
 34     //insertFirst(phead, 11, 100);
 35     //ShowAll(phead);
 36 
 37     printf("排序前:");
 38     ShowAll(phead);
 39     printf("\n\n");
 40 
 41     //bubbleSort(phead);
 42     quickSort(phead, NULL);
 43     
 44     printf("\n\n");
 45     printf("排序后:");
 46     ShowAll(phead);
 47     printf("\n");
 48 
 49     printf("%d\n", getNum2(phead));
 50 
 51     phead = revList1(phead);
 52     ShowAll(phead);
 53     printf("\n");
 54     phead = revList2(phead);
 55     ShowAll(phead);
 56     printf("\n");
 57 
 58     Node *phead1 = NULL;
 59     phead1 = addBack(phead1, 1);
 60     phead1 = addBack(phead1, 3);
 61     phead1 = addBack(phead1, 5);
 62     phead1 = addBack(phead1, 7);
 63     phead1 = addBack(phead1, 9);
 64 
 65     Node *phead2 = NULL;
 66     phead2 = addBack(phead2, 2);
 67     phead2 = addBack(phead2, 4);
 68     phead2 = addBack(phead2, 6);
 69     phead2 = addBack(phead2, 8);
 70 
 71     printf("\n\n\n");
 72     ShowAll(phead1);
 73     printf("\n");
 74     ShowAll(phead2);
 75     printf("\n");
 76 
 77     Node *phead3 = NULL;
 78     phead3 = mergeList(phead3, phead1, phead2);
 79     ShowAll(phead3);
 80     printf("\n");
 81 
 82     Node *pmid = getMid(phead3);
 83     printf("%d\n", pmid->data);
 84 
 85     Node *phead4 = NULL;
 86     phead4 = addBack(phead4, 1);
 87     phead4 = addBack(phead4, 2);
 88     phead4 = addBack(phead4, 3);
 89     phead4 = addBack(phead4, 4);
 90     phead4 = addBack(phead4, 5);
 91     phead4 = addBack(phead4, 6);
 92     phead4 = addBack(phead4, 7);
 93 
 94     Node *p = phead4;
 95     for (; p->pNext != NULL; p = p->pNext)
 96     {
 97     }
 98     p->pNext = phead4;
 99 
100     ShowCircleLink(phead4);    //打印环形链表
101     printf("\n");
102     printf("%d\n", judgeCircle(phead4));
103 
104     system("pause");
105 }

 

相关文章: