zoukankan      html  css  js  c++  java
  • 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(" plstB 初始数据: "); 431 ForEachList( plstB, display ); 432 433 ///测试 InsertElem 434 printf(" 向 plstA 位置3处插入元素(100,99)后: "); 435 pt.x = 100; pt.y = 99; 436 InsertElem( plstA, 3, &pt ); //向 plstA 位置 3 处插入 pt 437 ForEachList( plstA, display ); 438 439 ///测试 DeleteElem 440 printf(" 删除 plstB 位置0处的元素后: "); 441 DeleteElem( plstB, 0 ); //删除 plstA 位置 0 处的元素 442 ForEachList( plstB, display ); 443 444 ///测试 IsEmpty、GetLength 445 printf(" 线性表 plstA 是否为空: %d ", IsEmpty(plstA) ); 446 printf("线性表 plstB 的长度: %d ", GetLength(plstB) ); 447 448 ///测试 GetElem 449 GetElem( plstA, 5, &pt ); 450 printf("获取 plstA 位置 5 的元素: (%d, %d) ", pt.x, pt.y ); 451 452 ///测试 FindElem 453 pt.x = 6; pt.y = 6; 454 printf("获取元素(6,6)在线性表plstA中的位置: %d ", FindElem(plstA, 0, &pt)); 455 456 ///测试 GetPriorElem 457 GetPriorElem( plstA, &pt, &pt2 ); 458 printf("获取pt=(6,6)在plstA中的前驱节点: (%d,%d) ", pt2.x, pt2.y); 459 460 ///测试 GetNextElem 461 GetNextElem( plstA, &pt, &pt2 ); 462 printf("获取pt=(6,6)在plstA中的后继节点: (%d,%d) ", pt2.x, pt2.y); 463 464 ///测试 ListCpy 465 printf(" 将 plstB 复制到 plstA 后: "); 466 ListCpy( plstA, plstB ); 467 ForEachList( plstA, display ); 468 printf(" plstA长度=%d ", GetLength(plstA)); 469 470 ///测试 ListCat 471 printf(" 将 plstB 连接到 plstA 后: "); 472 ListCat( plstA, plstB ); 473 ForEachList( plstA, display ); 474 printf(" plstA长度=%d ", GetLength(plstA)); 475 476 ///测试 ClearList 477 printf(" 置空 plstA 线性表: "); 478 ClearList(plstA); 479 printf("plstA 长度=%d ", GetLength(plstA)); 480 481 ///测试 DestroyList 482 printf("销毁 plstA.."); 483 DestroyList(plstA); 484 485 return 0; 486 }

    若代码存在 bug 或程序缺陷, 请留言反馈, 谢谢。                                                                                                                                                                                                                                                                                       

  • 相关阅读:
    第一次作业
    C语言I博客作业02
    C语言|博客作业11
    C语言I博客作业10
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    JDK-14 & Eclipse & Hello World!
  • 原文地址:https://www.cnblogs.com/mr-wid/p/3383042.html
Copyright © 2011-2022 走看看