• 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 或程序缺陷, 请留言反馈, 谢谢。                                                                                                                                                                                                                                                                                       

  • 相关阅读:
    软件测试人员的年终绩效考核怎么应对
    收藏
    顶踩组件 前后两版
    订阅组件
    hdu 1963 Investment 完全背包
    hdu 4939 Stupid Tower Defense 动态规划
    hdu 4405 Aeroplane chess 动态规划
    cf 414B Mashmokh and ACM 动态规划
    BUPT 202 Chocolate Machine 动态规划
    hdu 3853 LOOPS 动态规划
  • 原文地址:https://www.cnblogs.com/mr-wid/p/3383042.html
Copyright © 2020-2023  润新知