一個單鏈式實現的線性表 mList (GCC編譯)。函數
1 /** 2 * @brief 線性表的鏈式實現 (單鏈表) 3 * @author wid 4 * @date 2013-10-21 5 * 6 * @note 若代碼存在 bug 或程序缺陷, 請留言反饋, 謝謝! 7 */ 8 9 #include <stdio.h> 10 #include <stdlib.h> 11 12 #define TRUE 1 13 #define FALSE 0 14 15 typedef struct 16 { 17 int x; 18 int y; 19 }Point2D; //Point2D 結構 20 typedef Point2D ElemType; //聲明 Point2D 結構的別名 ElemType 21 22 typedef struct LNode 23 { 24 Point2D pt; 25 struct LNode *next; 26 }ListNode; //線性表數據項結構 27 28 typedef struct 29 { 30 ListNode *head; //數據項頭節點 31 int length; //線性表長度 32 }mList; //線性表 mList 結構 33 34 35 //線性表方法聲明 36 mList *CreateList(); ///建立一個空的線性表 37 void DestroyList( mList *pList ); ///銷燬一條線性表 38 void ClearList( mList *pList ); ///置空一條線性表 39 int GetLength( mList *pList ); ///獲取線性表當前長度 40 int IsEmpty( mList *pList ); ///檢測線性表是否爲空 41 int AppendElem( mList *pList, ElemType *pt ); ///向線性表末尾添加一個元素 42 int InsertElem( mList *pList, int nPos, ElemType *pt ); ///向線性表中插入一個元素 43 int DeleteElem( mList *pList, int nPos ); ///從線性表中刪除一個元素 44 int GetElem( mList *pList, int nPos, ElemType *pt ); ///獲取線性表中某位置上的元素 45 int FindElem( mList *pList, int nPos, ElemType *pt ); ///從某位置起查找某元素在線性表中第一次出現的位置 46 int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt ); ///從線性表中獲取 pt 的前驅節點到 prior_pt 47 int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt ); ///從線性表中獲取 pt 的後繼節點到 next_pt 48 void ForEachList( mList *pList, void (*func)(ElemType *pt) ); ///對線性表中每一個元素執行 func 函數 49 int ListCpy( mList *pDestList, mList *pSrcList ); ///將一線性表複製到另外一線性表後 50 int ListCat( mList *pDestList, mList *pSrcList ); ///將一線性錶鏈接到另外一線性表後 51 52 53 //線性表方法實現 54 55 /** 56 * @brief 建立一個空的線性表 57 * 58 * @return 指向建立的線性表的指針 59 */ 60 mList *CreateList() 61 { 62 mList *pList = (mList *)malloc(sizeof(mList)); 63 pList->head = (ListNode *)malloc(sizeof(ListNode)); 64 pList->head->next = NULL; 65 pList->length = 0; 66 67 return pList; 68 } 69 70 /** 71 * @brief 銷燬一條線性表 72 * 73 * @param 指向待銷燬的線性表的指針 74 * 75 * @return void 76 */ 77 void DestroyList( mList *pList ) 78 { 79 ListNode *pm = pList->head, *pn = NULL; 80 while( pm != NULL ) 81 { 82 pn = pm->next; 83 free(pm); 84 pm = pn; 85 } 86 free(pList); 87 pList = NULL; 88 } 89 90 /** 91 * @brief 置空一條線性表 92 * 93 * @param 指向待置空的線性表指針 94 * 95 * @return void 96 */ 97 void ClearList( mList *pList ) 98 { 99 ListNode *pm = pList->head, *pn = NULL; 100 while( pm != NULL ) 101 { 102 pn = pm->next; 103 free(pm); 104 pm = pn; 105 } 106 pList->head->next = NULL; 107 pList->length = 0; 108 } 109 110 /** 111 * @brief 獲取線性表當前長度 112 * 113 * @param 指針待獲取長度的線性表的指針 114 * 115 * @return 返回獲取到的線性表長度 116 */ 117 int GetLength( mList *pList ) 118 { 119 return pList->length; 120 } 121 122 /** 123 * @brief 檢測線性表是否爲空 124 * 125 * @param pList 指向待檢測的線性表的指針 126 * 127 * @return 若爲空則返回 TRUE, 不然返回 FALSE 128 */ 129 int IsEmpty( mList *pList ) 130 { 131 return pList->length == 0 ? TRUE : FALSE; 132 } 133 134 /** 135 * @brief 向線性表末尾添加一個元素 136 * 137 * @param pList 目標線性表 138 * @param pe 指向待添加元素的指針 139 * 140 * @return 返回添加成功後當前線性表長度 141 */ 142 int AppendElem( mList *pList, ElemType *pt ) 143 { 144 ListNode *pm = pList->head, *pn = NULL; 145 146 while( pm->next != NULL ) { pm = pm->next; }; 147 pn = (ListNode *)malloc(sizeof(ListNode)); 148 pn->pt.x = pt->x; 149 pn->pt.y = pt->y; 150 pn->next = NULL; 151 pm->next = pn; 152 153 return ++pList->length; 154 } 155 156 /** 157 * @brief 向線性表中插入一個元素 158 * 159 * @param pList 指向待插入元素的線性表 160 * @param nPos 插入的位置 161 * @param pt 指向待插入的元素的指針 162 * 163 * @return 若插入成功則返回插入後線性表當前長度, 不然返回 -1 164 * 165 * @note 插入位置 nPos 從 0 計起 166 */ 167 int InsertElem( mList *pList, int nPos, ElemType *pt ) 168 { 169 ListNode *pm = pList->head, *pn = NULL; 170 171 if( nPos < 0 || nPos > pList->length - 1 ) ///插入位置是否在線性表內 172 return -1; 173 174 int n = 0; 175 for( n = 0; n < nPos; ++n, (pm = pm->next) ); 176 pn = (ListNode *)malloc(sizeof(ListNode)); 177 pn->pt.x = pt->x; 178 pn->pt.y = pt->y; 179 180 pn->next = pm->next; 181 pm->next = pn; 182 183 return ++pList->length; 184 } 185 186 /** 187 * @brief 從線性表中刪除一個元素 188 * 189 * @param pList 指向待刪除元素的線性表指針 190 * @param nPos 待刪除元素的位置 191 * 192 * @return 若刪除成功則返回刪除後線性表當前長度, 不然返回 -1 193 * 194 * @note 刪除位置 nPos 從 0 計起 195 */ 196 int DeleteElem( mList *pList, int nPos ) 197 { 198 ListNode *pm = pList->head, *pn = NULL; 199 200 if( nPos < 0 || nPos > pList->length - 1 ) ///刪除位置是否在線性表內 201 return -1; 202 203 int i = 0; 204 for( i = 0; i < nPos; ++i, (pm = pm->next) ); 205 pn = pm->next; 206 pm->next = pn->next; 207 free(pn); 208 209 return --pList->length; 210 } 211 212 /** 213 * @brief 獲取線性表中某位置上的元素 214 * 215 * @param pList 指向待獲取元素的線性表指針 216 * @param nPos 元素在線性表中的位置 217 * @param pt 指向存放獲取到的元素的指針 218 * 219 * @return 若獲取成功, 返回 TRUE, 不然返回 FALSE 220 * 221 * @note 元素位置從 0 計起 222 */ 223 int GetElem( mList *pList, int nPos, ElemType *pt ) 224 { 225 int n = nPos; 226 if( n < 0 || n > pList->length - 1 ) 227 return FALSE; 228 229 ListNode *pm = pList->head; 230 for( n = 0; n <= nPos; ++n, (pm = pm->next) ); 231 pt->x = pm->pt.x; 232 pt->y = pm->pt.y; 233 234 return TRUE; 235 } 236 237 /** 238 * @brief 從某位置起查找某元素在線性表中第一次出現的位置 239 * 240 * @param pList 指向待查找元素的線性表的指針 241 * @param nPos 查找起始位置 242 * @param pt 指向待查找的元素的指針 243 * 244 * @return 若找到, 則返回元素所在的位置, 不然返回 -1 245 * 246 * @note 起始位置由 0 計起 247 */ 248 int FindElem( mList *pList, int nPos, ElemType *pt ) 249 { 250 int n = nPos; 251 if( n < 0 || n > pList->length - 1 ) 252 return -1; 253 254 ListNode *pm = pList->head; 255 for( n = 0; n <= nPos; ++n, (pm = pm->next) ); 256 for( ; pm != NULL; ++n ) 257 { 258 if( (pm->pt.x == pt->x) && (pm->pt.y == pt->y) ) 259 return n-1; 260 261 pm = pm->next; 262 } 263 264 return -1; 265 } 266 267 /** 268 * @brief 獲取某 pt 元素的前驅節點到 prior_pt 269 * 270 * @param 指向待獲取前驅節點的線性表指針 271 * @param pt 指向目標節點的指針 272 * @param prior_pt 存放目標節點 pt 的前驅節點 273 * 274 * @return 若成功獲取前驅節點, 返回該前驅節點在線性表中的位置, 不然返回 -1 275 * 276 * @note 元素位置從 0 計起 277 */ 278 int GetPriorElem( mList *pList, ElemType *pt, ElemType *prior_pt ) 279 { 280 ListNode *pm = pList->head; 281 int ncnt = 0; 282 while( pm->next != NULL ) 283 { 284 if( pm->next->pt.x == pt->x && pm->next->pt.y == pt->y ) 285 { 286 if( ncnt != 0 ) ///不爲首節點 287 { 288 prior_pt->x = pm->pt.x; 289 prior_pt->y = pm->pt.y; 290 return ncnt - 1; 291 } 292 else return -1; ///不存在前驅節點 293 } 294 pm = pm->next; 295 ++ncnt; 296 } 297 298 return -1; 299 } 300 301 /** 302 * @brief 獲取某 pt 元素的後繼節點到 next_pt 303 * 304 * @param 指向待獲取先後繼點的線性表指針 305 * @param pt 指向目標節點的指針 306 * @param prior_pt 存放目標節點 pt 的後繼節點 307 * 308 * @return 若成功獲取後繼節點, 返回該後繼節點在線性表中的位置, 不然返回 -1 309 * 310 * @note 元素位置從 0 計起 311 */ 312 int GetNextElem( mList *pList, ElemType *pt, ElemType *next_pt ) 313 { 314 ListNode *pm = pList->head; 315 int ncnt = 0; 316 while( (pm = pm->next) != NULL ) 317 {
if( ncnt == pList->length ) //bug修復, 不存在後繼節點
return -1;
318 if( pm->pt.x == pt->x && pm->pt.y == pt->y ) 319 { 320 if( pm->next != NULL ) 321 { 322 next_pt->x = pm->next->pt.x; 323 next_pt->y = pm->next->pt.y; 324 325 return ncnt + 1; 326 } 327 } 328 ++ncnt; 329 } 330 331 return -1; 332 } 333 334 /** 335 * @brief 對線性表中每一個元素執行 func 函數 336 * 337 * @param pList 指向待處理的線性表的指針 338 * @param func 傳入的函數指針 339 * 340 * @return void 341 */ 342 void ForEachList( mList *pList, void (*func)(ElemType *pt) ) 343 { 344 ListNode *pm = pList->head; 345 while( (pm = pm->next) != NULL ) 346 func( &pm->pt ); 347 } 348 349 /** 350 * @brief 將 pSrcList 性表複製到 pDestList 線性表後 351 * 352 * @param pDestList 指向目標線性表指針 353 * @param pSrcList 指向源線性表指針 354 * 355 * @return 返回複製後目標線性表長度 356 */ 357 int ListCpy( mList *pDestList, mList *pSrcList ) 358 { 359 ListNode *pm = pDestList->head; 360 ListNode *pn = pSrcList->head; 361 ListNode *ptmp = NULL; 362 363 while( pm->next != NULL ) pm = pm->next; 364 while( (pn = pn->next) != NULL ) 365 { 366 ptmp = (ListNode *)malloc(sizeof(ListNode)); 367 ptmp->pt.x = pn->pt.x; 368 ptmp->pt.y = pn->pt.y; 369 pm->next = ptmp; 370 pm = pm->next; 371 } 372 pm->next = NULL; 373 pDestList->length += pSrcList->length; 374 375 return pDestList->length; 376 } 377 378 /** 379 * @brief 將 pSrcList 性錶鏈接到 pDestList 線性表後 380 * 381 * @param pDestList 指向目標線性表指針 382 * @param pSrcList 指向源線性表指針 383 * 384 * @return 返回鏈接後目標線性表長度 385 * 386 * @note 鏈接後 pSrcList 線性表將被銷燬 387 */ 388 int ListCat( mList *pDestList, mList *pSrcList ) 389 { 390 ListNode *pm = pDestList->head; 391 while( pm->next != NULL ) pm = pm->next; 392 pm->next = pSrcList->head->next; 393 pDestList->length += pSrcList->length; 394 free( pSrcList ); 395 396 return pDestList->length; 397 } 398 399 //測試 mList 400 401 void display( ElemType *pt ) 402 { 403 printf("(%d,%d) ", pt->x, pt->y); 404 } 405 406 int main() 407 { 408 mList *plstA = CreateList(), *plstB = CreateList(); //建立 plst 與 plst2 兩根空線性表 409 ElemType pt, pt2; //兩個 ElemType 型元素 410 411 int i = 0; 412 for( i = 0; i < 10; ++i ) 413 { 414 pt.x = i; 415 pt.y = i; 416 AppendElem( plstA, &pt ); //向 plst 循環添加 (0,0) 至 (10,10) 417 } 418 419 for( i = 55; i < 60; ++i ) 420 { 421 pt.x = i; 422 pt.y = i; 423 AppendElem( plstB, &pt ); //向 plst 循環添加 (55,55) 至 (60,60) 424 } 425 426 ///測試 ForEachList 427 printf("plstA 初始數據: "); 428 ForEachList( plstA, display ); //對線性表中每一個元素執行 display 函數 429 430 printf("\nplstB 初始數據: "); 431 ForEachList( plstB, display ); 432 433 ///測試 InsertElem 434 printf("\n\n向 plstA 位置3處插入元素(100,99)後:\n"); 435 pt.x = 100; pt.y = 99; 436 InsertElem( plstA, 3, &pt ); //向 plstA 位置 3 處插入 pt 437 ForEachList( plstA, display ); 438 439 ///測試 DeleteElem 440 printf("\n\n刪除 plstB 位置0處的元素後:\n"); 441 DeleteElem( plstB, 0 ); //刪除 plstA 位置 0 處的元素 442 ForEachList( plstB, display ); 443 444 ///測試 IsEmpty、GetLength 445 printf("\n\n線性表 plstA 是否爲空: %d\n", IsEmpty(plstA) ); 446 printf("線性表 plstB 的長度: %d\n", GetLength(plstB) ); 447 448 ///測試 GetElem 449 GetElem( plstA, 5, &pt ); 450 printf("獲取 plstA 位置 5 的元素: (%d, %d)\n", pt.x, pt.y ); 451 452 ///測試 FindElem 453 pt.x = 6; pt.y = 6; 454 printf("獲取元素(6,6)在線性表plstA中的位置: %d\n", FindElem(plstA, 0, &pt)); 455 456 ///測試 GetPriorElem 457 GetPriorElem( plstA, &pt, &pt2 ); 458 printf("獲取pt=(6,6)在plstA中的前驅節點: (%d,%d)\n", pt2.x, pt2.y); 459 460 ///測試 GetNextElem 461 GetNextElem( plstA, &pt, &pt2 ); 462 printf("獲取pt=(6,6)在plstA中的後繼節點: (%d,%d)\n", pt2.x, pt2.y); 463 464 ///測試 ListCpy 465 printf("\n將 plstB 複製到 plstA 後:\n"); 466 ListCpy( plstA, plstB ); 467 ForEachList( plstA, display ); 468 printf("\nplstA長度=%d\n", GetLength(plstA)); 469 470 ///測試 ListCat 471 printf("\n將 plstB 鏈接到 plstA 後:\n"); 472 ListCat( plstA, plstB ); 473 ForEachList( plstA, display ); 474 printf("\nplstA長度=%d\n", GetLength(plstA)); 475 476 ///測試 ClearList 477 printf("\n置空 plstA 線性表:\n"); 478 ClearList(plstA); 479 printf("plstA 長度=%d\n", GetLength(plstA)); 480 481 ///測試 DestroyList 482 printf("銷燬 plstA.."); 483 DestroyList(plstA); 484 485 return 0; 486 }
若代碼存在 bug 或程序缺陷, 請留言反饋, 謝謝。 測試