圣龙扬特-AVR电子

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 936|回复: 1
打印 上一主题 下一主题

[源代码] C语言单向链表

[复制链接]

6

主题

0

好友

627

积分

高级会员

Rank: 4

UID
43
帖子
33
精华
0
注册时间
2013-2-27
在线时间
8 小时
跳转到指定楼层
楼主
发表于 2013-4-12 18:36:49 |只看该作者 |倒序浏览
本帖最后由 avrbase_lei 于 2013-4-12 18:38 编辑

再贴点儿工作用到的代码。单向链表。
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <assert.h>


  5. typedef unsigned char snl_u8;
  6. typedef signed char snl_s8;

  7. typedef unsigned short int snl_u16;
  8. typedef signed short int snl_s16;

  9. typedef unsigned int snl_u32;
  10. typedef signed int snl_s32;

  11. typedef char snl_char;
  12. typedef unsigned short snl_wchar;

  13. typedef enum {snl_false, snl_true} snl_bool;


  14. typedef struct single_node_list{
  15. struct single_node_list *next;
  16. void *vp;
  17. }SingleNodeList_t;
复制代码
在定义些函数接口,方便调试。
  1. #define snl_trace printf
  2. #define snl_malloc malloc
  3. #define snl_mfree free
  4. #define snl_assert assert
  5. #define snl_memset memset
  6. #define snl_memcpy memcpy
  7. #define snl_memcmp memcmp
复制代码
接着就是源代码了。
  1. /*******************************************************************************
  2. ** 函数: snl_alloc_new
  3. ** 功能: 申请一个新的节点内存
  4. ** 作者: avrbase_lei
  5. *******/
  6. static SingleNodeList_t *snl_alloc_new(void)
  7. {
  8. SingleNodeList_t *newnode = NULL;

  9. newnode = (SingleNodeList_t*)snl_malloc(sizeof(SingleNodeList_t));
  10. snl_assert(NULL != newnode);
  11. snl_memset((void*)newnode, 0, sizeof(SingleNodeList_t));

  12. return newnode;
  13. }
复制代码
  1. /*******************************************************************************
  2. ** 函数: snl_insert
  3. ** 功能: 在链表上插入一个新的节点.
  4. ** 入参: rootpp 指向根节点的指针.
  5. ** addvp 需要插入链表的数据地址.
  6. ** front_insert 是否插入在匹配到的节点的前面.
  7. ** private_compare 比较函数, 比较成功后依front_insert决定插入位置.
  8. ** 若直到链表尾都未匹配成功则默认插入链表为尾.
  9. ** 若private_compare为空则插入链表尾.
  10. ** 返回: 返回插入结果.
  11. ** 作者: avrbase_lei
  12. *******/
  13. static snl_bool snl_insert(
  14. SingleNodeList_t **rootpp,
  15. void *addvp,
  16. void *compare_vp,
  17. snl_bool front_insert,
  18. snl_bool (*private_compare)(void *, void *))
  19. {
  20. snl_bool inserted = snl_false;
  21. snl_bool is_root_pos = snl_true;
  22. SingleNodeList_t *newnode = NULL;
  23. SingleNodeList_t *currnode = NULL, *prevnode = NULL;

  24. do{
  25. if(NULL == rootpp)
  26. break;

  27. newnode = snl_alloc_new();
  28. if(NULL == newnode)
  29. break;
  30. newnode->vp = addvp;

  31. if(NULL == private_compare || NULL == compare_vp)
  32. {
  33. if(NULL == *rootpp)
  34. {
  35. *rootpp = newnode;
  36. }
  37. else
  38. {
  39. currnode = *rootpp;
  40. while(NULL != currnode->next)
  41. {
  42. currnode = currnode->next;
  43. }

  44. currnode->next = newnode;
  45. }

  46. inserted = snl_true;
  47. break;
  48. }
  49. currnode = *rootpp;
  50. is_root_pos = snl_true;
  51. inserted = snl_false;
  52. while(NULL != currnode && !inserted)
  53. {
  54. if(private_compare(currnode->vp, compare_vp))
  55. {
  56. //如果是根节点匹配到了, 则根节点要指向下一个节点
  57. if(is_root_pos)
  58. {
  59. if(front_insert)
  60. {
  61. newnode->next = *rootpp;
  62. *rootpp = newnode;
  63. }
  64. else
  65. {
  66. newnode->next = (*rootpp)->next;
  67. (*rootpp)->next = newnode;
  68. }
  69. }
  70. else
  71. {
  72. if(front_insert)
  73. {
  74. newnode->next = currnode;
  75. prevnode->next = newnode;
  76. }
  77. else
  78. {
  79. newnode->next = currnode->next;
  80. currnode->next = newnode;
  81. }
  82. }

  83. inserted = snl_true;
  84. }
  85. else
  86. {
  87. prevnode = currnode;
  88. currnode = currnode->next;
  89. is_root_pos = snl_false;
  90. }
  91. }

  92. if(!inserted)
  93. {
  94. prevnode->next = newnode;
  95. inserted = snl_true;
  96. }

  97. }while(0);

  98. return inserted;
  99. }
复制代码
  1. /*******************************************************************************
  2. ** 函数: snl_delete
  3. ** 功能: 删除链表上snl_compare匹配到的指定的节点
  4. ** 如果比较函数为空则执行全部删除功能.
  5. ** 入参: rootpp 根节点
  6. ** com_node_data_p 用于参与匹配的数据
  7. ** traval_del 是否遍历删除链表中的节点. 否则删除离根节点最近的节点
  8. ** private_compare 数据匹配函数, 其返回值用于决定是否删除
  9. ** private_delete 数据删除函数, 本参数必须非空, 否则无法删除任何数据
  10. ** 返回: 返回删除的节点个数
  11. ** 作者: avrbase_lei
  12. *******/
  13. static snl_u32 snl_delete(
  14. SingleNodeList_t **rootpp,
  15. void *cmp_node_data_p,
  16. snl_bool travel_del,
  17. snl_bool (*private_compare)(void *, void *),
  18. void (*private_delete)(void *))
  19. {
  20. snl_u32 deleted_ct = 0;
  21. snl_bool is_del_root = snl_true;
  22. SingleNodeList_t *currnode = NULL, *prevnode = NULL, *delnode = NULL;

  23. do{
  24. if(NULL == rootpp)
  25. break;

  26. if(NULL == private_delete)
  27. break;

  28. if(NULL == private_compare)
  29. {
  30. currnode = *rootpp;
  31. while(NULL != currnode)
  32. {
  33. delnode = currnode;
  34. currnode = currnode->next;
  35. private_delete(delnode->vp);
  36. snl_mfree(delnode);
  37. deleted_ct ++;
  38. }

  39. *rootpp = NULL;

  40. break;
  41. }

  42. if(NULL == cmp_node_data_p)
  43. break;

  44. currnode = *rootpp;
  45. is_del_root = snl_true;
  46. while(NULL != currnode)
  47. {
  48. if(private_compare(currnode->vp, cmp_node_data_p))
  49. {
  50. //如果是根节点匹配到了, 则根节点要指向下一个节点
  51. if(is_del_root)
  52. {
  53. *rootpp = prevnode = currnode->next;
  54. }
  55. else
  56. {
  57. prevnode->next = currnode->next;
  58. is_del_root = snl_false;
  59. }

  60. //当前节点指向下一个节点
  61. delnode = currnode;
  62. currnode = currnode->next;

  63. //删除节点
  64. private_delete(delnode->vp);
  65. snl_mfree(delnode);
  66. deleted_ct ++;

  67. //非遍历删除则中断循环
  68. if(!travel_del)
  69. break;
  70. }
  71. else
  72. {
  73. prevnode = currnode;
  74. currnode = currnode->next;
  75. is_del_root = snl_false;
  76. }
  77. }

  78. }while(0);

  79. return deleted_ct;
  80. }

复制代码
估计排版很恶心。
回复

使用道具 举报

6

主题

0

好友

627

积分

高级会员

Rank: 4

UID
43
帖子
33
精华
0
注册时间
2013-2-27
在线时间
8 小时
沙发
发表于 2013-4-12 18:41:49 |只看该作者
还要自己测试下。

  1. <P>/*******************************************************************************
  2. ** 函数: test_print_list
  3. ** 功能: 测试用的打印链表所有数据信息的函数
  4. ** 入参: rootpp 根节点指针
  5. ** 返回:
  6. ** 作者: avrbase_lei
  7. *******/
  8. static void test_print_list(SingleNodeList_t **rootpp)
  9. {
  10. SingleNodeList_t *tmpnode = *rootpp;</P>
  11. <P>    snl_trace("print list:\r\n  value: ");
  12. while(NULL != tmpnode)
  13. {
  14.         snl_trace("%d ", (snl_u32)tmpnode->vp);
  15.         
  16.   tmpnode = tmpnode->next;
  17. }
  18.     snl_trace("\r\nprint end.\r\n");
  19. }
  20. </P>
复制代码
这排版,毫无美观可言。
  1. /*******************************************************************************
  2. ** 函数: test_delete
  3. ** 功能: 测试用的节点数据删除函数. 函数体可以为空
  4. ** 入参: nodevp 节点指针所指向的数据地址
  5. ** 返回:
  6. ** 作者: avrbase_lei
  7. *******/
  8. static void test_delete(void *nodevp)
  9. {
  10. /* do nothing. */
  11. }

复制代码
  1. /*******************************************************************************
  2. ** 函数: test_compare
  3. ** 功能: 测试用的比较函数
  4. ** 入参: node 节点指针
  5. ** cpdt 参与匹配的数据
  6. ** 返回: 返回匹配结果
  7. ** 作者: avrbase_lei
  8. *******/
  9. static snl_bool test_compare(void *nodevp, void *cpdtp)
  10. {
  11. if(NULL == cpdtp || NULL == nodevp)
  12. return snl_false;

  13. return (snl_bool)((snl_u32)(nodevp) == (snl_u32)cpdtp);
  14. }
复制代码
  1. /*******************************************************************************
  2. ** 函数: test_main
  3. ** 功能: 测试入口函数
  4. ** 入参:
  5. ** 返回:
  6. ** 作者: avrbase_lei
  7. *******/
  8. void test_main(void)
  9. {
  10. const snl_u32 test_loop_ct = 5;
  11. snl_u32 i, total, cmpdat;
  12. SingleNodeList_t *rootp = NULL;

  13. //insert
  14. for(i=0; i<test_loop_ct; i++)
  15. {
  16. total = snl_insert(&rootp, (void*)i, NULL, snl_false, NULL);
  17. }

  18. //print
  19. test_print_list(&rootp);

  20. //delete
  21. for(i=0; i<test_loop_ct; i++)
  22. {
  23. cmpdat = rand()%test_loop_ct;
  24. snl_trace("%dst delete, to be delete value is %d. \r\n", i, cmpdat);
  25. cmpdat = snl_delete(&rootp, (void *)cmpdat, snl_false, test_compare, test_delete);
  26. snl_trace("snl_delete return %d.\r\n", cmpdat);

  27. test_print_list(&rootp);
  28. }

  29. //free all
  30. snl_delete(&rootp, NULL, snl_true, NULL, test_delete);
  31. test_print_list(&rootp);

  32. }
复制代码
  1. int main(int argc, char **argv)
  2. {
  3. test_main();

  4. printf("程序运行结束!\r\n");
  5. getchar();
  6. return 0;
  7. }
复制代码
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

Archiver|手机版|圣龙扬特-AVR电子 ( 鲁ICP备05022832号 )

GMT+8, 2024-6-24 02:44 , Processed in 0.201661 second(s), 17 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部