链表基本操作实现
前言
这应该算是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 }