C語言 線性表 鏈式表結構 實現

一個單鏈式實現的線性表 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 或程序缺陷, 請留言反饋, 謝謝。                                                                                                                                                                                                                                                                                       測試

相關文章
相關標籤/搜索