Loading

链表基本操作实现

前言

这应该算是Mark Allen Weiss《数据结构和算法分析——C语言描述》的家庭作业。从前的学习笔记保存在OneNote,正好借着写博的机会翻出来复习。

正文

链表的定义很简单,每个节点包含数据域和指针域。

下面是单链表的实现,包含list.h和list.c两个文件。list.h是接口声明,涉及的操作也会在这里说明;list.c就是接口实现了。

  1 /*
  2   规范化单链表:
  3   
  4  (1)构建带头结点的链表
  5  (2)规范化操作集
  6 */
  7 
  8 /*接口声明*/
  9 
 10 #include <stdbool.h>
 11 
 12 typedef int ElementType;
 13 
 14 #ifndef _LIST_H
 15 #define _LIST_H
 16 
 17 struct Node;
 18 
 19 typedef struct Node * PtrToNode;
 20 typedef PtrToNode List;
 21 typedef PtrToNode Position;
 22 
 23 /*操作集*/
 24 
 25 /*创建一个头结点,并将其设为空表*/
 26 List MakeEmpty(List L);
 27 
 28 /*判断链表是否为空表,若为空表返回ture,否则返回false*/
 29 bool IsEmpty(List L);
 30 
 31 /*判断位置P是否为尾元素,若是返回ture,否则返回false*/
 32 bool IsLast(Position P,List L);
 33 
 34 /*查找元素在链表中的位置,若未找到返回NULL*/
 35 Position Find(ElementType X,List L);
 36 
 37 /*删除元素,从链表中*/
 38 void Delete(ElementType X,List L);
 39 
 40 /*查找元素在链表中的位置,但返回上个元素的位置。若返回尾部说明未找到目标元素*/
 41 Position FindPrevious(ElementType X,List L);
 42 
 43 /*将元素插入指定位置P的后面*/
 44 void Isert(ElementType X,List L,Position P);
 45 
 46 /*删除链表,但依然保留头结点*/
 47 void DeleteList(List L);
 48 
 49 /*报告链表头结点位置*/
 50 Position Header(List L);
 51 
 52 /*报告链表首元素位置*/
 53 Position First(List L);
 54 
 55 /*报告位置P的下个位置*/
 56 Position Advance(Position P);
 57 
 58 /*取出位置P中元素*/
 59 ElementType Retrieve(Position P);
 60 
 61 /*打印链表*/
 62 void PrintfList(List L);
 63 
 64 /*交换两个相邻元素,BeforeP指向相邻元素前面的一个元素*/
 65 void SwapWithNext(Position BeforeP,List L); 
 66 
 67 /*打印链表L中由链表P所指定位置上的元素(L和P是升序链表)*/
 68 void PrintLots(List L,List P);
 69 
 70 /*求两个升序链表的交集*/
 71 List Intersect(List L1,List L2);
 72 
 73 /*求两个升序链表的并集*/
 74 List Union(List L1,List L2);
 75 
 76 /*将链表反转,O(N)*/
 77 void Reverse(List L); 
 78 
 79 #endif 
 80 
 81 #include <stdio.h>
 82 #include <stdlib.h>
 83 #include "list.h"
 84 
 85 /*声明特定的结构*/
 86 struct Node
 87 {
 88     ElementType Element;
 89     struct Node *  Next;
 90 };
 91 
 92 /*==================================================================================*/
 93 
 94 /*接口实现*/
 95 /*void MakeEmpty(List * L)
 96 {
 97    *L = (List)malloc(sizeof(struct Node)); 
 98     if (*L == NULL)
 99     {
100        printf("初始化失败,退出程序\n");
101        exit(1);
102     }
103     
104     (*L)->Next = NULL;
105 }*/
106 
107  List MakeEmpty(List L)
108 {
109     if (L != NULL)
110         DeleteList(L);//如果链表非空,则删除链表
111     L = (List)malloc(sizeof(struct Node));
112     if (L == NULL)
113     {
114        printf("初始化失败,退出程序\n");
115        exit(1);
116     }
117       
118     L->Next = NULL;
119     return L;
120 }
121 
122 bool IsEmpty(List L)
123 {
124     return L->Next == NULL;
125 }
126 
127 bool IsLast(Position P,List L)
128 {
129     return P->Next == NULL;
130 }
131 
132 Position Find(ElementType X,List L)
133 {
134     Position P = L->Next;
135     
136     while (P != NULL && P->Element != X)
137         P = P->Next;
138         
139     return P;
140 }
141 
142 void Delete(ElementType X,List L)
143 {
144     Position LastElement = FindPrevious(X,L);
145     Position TheElement; 
146     
147     if (!IsLast(LastElement,L))    //LastElement不是尾部,说明找到X 
148     {
149        TheElement = LastElement->Next;
150        LastElement->Next = TheElement->Next;
151        free(TheElement);
152     }
153 }
154 
155 Position FindPrevious(ElementType X,List L)
156 {
157     Position P = L;
158     
159     while (P->Next != NULL && P->Next->Element != X)
160         P = P->Next;
161     
162     return P;
163 }
164 
165 void Isert(ElementType X,List L,Position P)
166 {
167     Position Temp;
168     
169     Temp = (List)malloc(sizeof(struct Node));
170     if (Temp == NULL)
171     {
172        printf("内存分配失败,退出程序\n");
173        exit(1);
174     }
175     
176     Temp->Element = X;
177     
178     Temp->Next = P->Next;
179     P->Next = Temp;
180 }
181 
182 void DeleteList(List L)
183 {
184     Position P = L->Next;
185     Position Temp;
186     
187     L->Next = NULL;       //保留头结点 
188     
189     while (P != NULL)
190     {
191         Temp = P->Next;
192         free(P);
193         P = Temp;
194     }
195 }
196 
197 Position Header(List L)
198 {
199     return L;
200 }
201 
202 Position First(List L)
203 {
204     return L->Next;
205 }
206 
207 Position Advance(Position P)
208 {
209     return P->Next;
210 }
211 
212 ElementType Retrieve(Position P)
213 {
214     return P->Element;
215 }
216 
217 void PrintfList(List L)
218 {
219     Position P;
220     
221     if (IsEmpty(L))
222        printf("List is empty!\n");
223     
224     P = First(L);
225     while (P != NULL)
226     {
227         printf("%3d",Retrieve(P));
228         P = Advance(P);
229     }
230     printf("\n");
231 }
232 
233 void SwapWithNext(Position BeforeP,List L)
234 {
235     Position P;
236     Position AfterP;
237     
238     P = Advance(BeforeP);
239     if (P != NULL)
240     {
241        AfterP = Advance(P);
242        if (AfterP != NULL)
243        {
244            P->Next = AfterP->Next;
245            BeforeP->Next = AfterP;
246            AfterP->Next = P;
247        }
248     }
249 }
250 
251 void PrintLots(List L,List P)
252 {
253     int count = 1;//链表L元素计数器,初始值指向第一个元素
254     Position LTemp;
255     Position PTemp;
256     
257     LTemp = First(L);
258     PTemp = First(P);
259     
260     /*当链表L和P任一为空停止打印*/
261     while (LTemp != NULL && PTemp != NULL)
262     {
263         if (count == PTemp->Element)   //判断是否打印当前元素
264         {
265            printf("%3d",LTemp->Element);
266            PTemp = Advance(PTemp);     //指向下个要打印的目标元素 
267         } 
268         
269         LTemp = Advance(LTemp);
270         count++;
271     }
272     printf("\n"); 
273 }
274 
275 
276 List Intersect(List L1,List L2)
277 {
278     List Result;
279     Position Ptr1;
280     Position Ptr2;
281     Position P;
282     
283     Result = MakeEmpty(NULL);
284     Ptr1 = First(L1);
285     Ptr2 = First(L2);
286     P = Header(Result);
287     
288     /*归并操作*/
289     while (Ptr1 != NULL && Ptr2 != NULL)
290     {
291         if (Ptr1->Element < Ptr2->Element)
292            Ptr1 = Advance(Ptr1);
293         
294         else if (Ptr1->Element > Ptr2->Element)
295            Ptr2 = Advance(Ptr2);
296            
297         else
298         {
299            Isert(Ptr1->Element,Result,P);
300            
301            Ptr1 = Advance(Ptr1);
302            Ptr2 = Advance(Ptr2);
303            P = Advance(P);
304         }
305     }
306     
307     return Result; 
308 }
309 
310 
311 
312 List Union(List L1,List L2)
313 {
314     List Result;
315     Position Ptr1;
316     Position Ptr2;
317     Position P;
318     
319     Result = MakeEmpty(NULL);
320     Ptr1 = First(L1);
321     Ptr2 = First(L2);
322     P = Header(Result);
323     
324     /*归并操作*/
325     while (Ptr1 != NULL&& Ptr2 != NULL)
326     {
327         if (Ptr1->Element < Ptr2->Element)
328         {
329            Isert(Ptr1->Element,Result,P);
330            Ptr1 = Advance(Ptr1);
331         }
332         
333         else if (Ptr1->Element > Ptr2->Element)
334         {
335            Isert(Ptr2->Element,Result,P);
336            Ptr2 = Advance(Ptr2);
337         }
338         
339         else
340         {
341            Isert(Ptr1->Element,Result,P);
342            Ptr1 = Advance(Ptr1);
343            Ptr2 = Advance(Ptr2);
344         }
345         
346         P = Advance(P);
347     }
348     
349     while (Ptr1 != NULL)
350     {
351         Isert(Ptr1->Element,Result,P);
352         Ptr1 = Advance(Ptr1);
353         P = Advance(P);
354     }
355     
356     while (Ptr2 != NULL)
357     {
358         Isert(Ptr2->Element,Result,P);
359         Ptr2 = Advance(Ptr2);
360         P = Advance(P);
361     }
362     
363     return Result;
364 }
365 
366 void Reverse(List L)
367 {
368     Position Temp;
369     Position P;
370     
371     if (IsEmpty(L) || L->Next->Next == NULL)
372        return;
373     
374     P = First(L);
375     L->Next = NULL;
376     
377     while (P != NULL)
378     {
379         Temp = Advance(P);
380         P->Next = First(L);
381         L->Next = P;
382         
383         P = Temp;
384     }
385 }

 

posted @ 2017-08-08 16:05  未夏  阅读(382)  评论(0编辑  收藏  举报