• c语言简单的双向链表的分析(可添加和删除节点)


    代码如下

    1. #include
    2. #include
    3. struct test
    4. {
    5. int x;
    6. struct test * next;
    7. struct test * last;
    8. };
    9. int node_nub=0;
    10. void delete_node_f(struct test *h,int n)
    11. {
    12. int i;
    13. if(h->next==NULL) {
    14. printf("node end!\n");
    15. exit(-1);
    16. }
    17. struct test *temp = h;
    18. for(i=0;i
    19. temp=temp->next;
    20. }
    21. struct test *Pnew = temp->next;
    22. temp->x = Pnew->x;
    23. temp->next = Pnew->next;
    24. free(Pnew);
    25. }
    26. void delete_node_b(struct test *b,int n)
    27. {
    28. int i;
    29. if(b->last==NULL) {
    30. printf("node end!\n");
    31. exit(-1);
    32. }
    33. struct test *temp = b;
    34. for(i=0;i
    35. temp=temp->last;
    36. }
    37. struct test *Pnew = temp->next;
    38. temp->x = Pnew->x;
    39. temp->next = Pnew->next;
    40. free(Pnew);
    41. }
    42. void delete_node_1(struct test *p)
    43. {
    44. if(p->next==NULL) {
    45. printf("node end!\n");
    46. exit(-1);
    47. }
    48. struct test *q = p->next;
    49. p->x = q->x;
    50. p->next = q->next;
    51. free(q);
    52. }
    53. void add_node_f(struct test *h,int n)
    54. {
    55. int i;
    56. struct test *temp = h;
    57. for(i=0;i
    58. temp=temp->next;
    59. }
    60. struct test *Pnew = (struct test *)malloc(sizeof(struct test));
    61. Pnew->x=n;
    62. Pnew->next = temp->next ;
    63. temp->next = Pnew;
    64. }
    65. void add_node_b(struct test *b,int n)
    66. {
    67. int i;
    68. struct test *temp = b;
    69. struct test *Pnew = (struct test *)malloc(sizeof(struct test));
    70. Pnew->x=node_nub-n;
    71. for(i=0;i
    72. temp=temp->last;
    73. }
    74. Pnew->next = temp->next ;
    75. temp->next = Pnew;
    76. }
    77. int main(void)
    78. {
    79. int i;
    80. struct test *head=NULL;
    81. struct test *tail=NULL;
    82. struct test *prev,*current;
    83. for(i=0;i<10;i++){
    84. current=(struct test*)malloc(sizeof(struct test));
    85. if(head==NULL)
    86. head=current;
    87. else
    88. prev->next = current;
    89. current->last = prev;
    90. current->next = NULL;
    91. current->x=i;
    92. prev=current;
    93. }
    94. tail = current;
    95. prev = tail;
    96. current = head;
    97. while(current!=NULL){
    98. node_nub++;
    99. current = current->next;
    100. }
    101. current = head;
    102. // delete_node_1(tail->last->last->next);
    103. add_node_f(head,2);
    104. delete_node_f(head,2);
    105. add_node_b(tail,9);
    106. delete_node_b(tail,9);
    107. while(current!=NULL){
    108. printf("x=%d\n",current->x);
    109. current = current->next;
    110. }
    111. return 0;
    112. }

    逐个分析

    1、头文件和结构体的定义,结构体中有一个值x,用于打印使链表可视化,打印出来的值即链表的位置id号,这个id号其实是不存在的只是在此方便分析,定义了另外两个分别是指向下一个节点地址的next指针和指向上一个节点的last;顺便定义了一个全局变量node_nub,用于保存该链表的节点的总数。

    1. #include
    2. #include
    3. struct test
    4. {
    5. int x;
    6. struct test * next;
    7. struct test * last;
    8. };
    9. int node_nub=0;

    2、从前到后的顺序删除节点的函数

    1. void delete_node_f(struct test *h,int n)
    2. {
    3. int i;
    4. if(h->next==NULL) {
    5. printf("node end!\n");
    6. exit(-1);
    7. }
    8. struct test *temp = h;
    9. for(i=0;i
    10. temp=temp->next;
    11. }
    12. struct test *Pnew = temp->next;
    13. temp->x = Pnew->x;
    14. temp->next = Pnew->next;
    15. free(Pnew);
    16. }

     h是head头,指的是首个节点的地址,n代表着第n个节点,首先判断该节点是否为尾节点,将temp代替h(也可以直接用h)用一个for循环到第n个节点,关键代码是后面的四行,创建一个新的结构体Pnew,它指向temp的下一个节点,然后将这个节点中保存的值赋值给目前节点即temp下一个节点next的指针也是复制过去,那么指针会指向相对于初始temp的下下个节点,于是乎就跳过了该节点,最后将其释放,完成顺序方式的节点删除。

    3、从后到前的顺序删除节点的函数,不然怎么叫双向链表呢! ( ̄▽ ̄)~*

    1. void delete_node_b(struct test *b,int n)
    2. {
    3. int i;
    4. if(b->last==NULL) {
    5. printf("node end!\n");
    6. exit(-1);
    7. }
    8. struct test *temp = b;
    9. for(i=0;i1;i++) {
    10. temp=temp->last;
    11. }
    12. struct test *Pnew = temp->next;
    13. temp->x = Pnew->x;
    14. temp->next = Pnew->next;
    15. free(Pnew);
    16. }

    其实基本和上述类似只是在for循环的地方用的是指向last的地址,而last是存放的前一个节点的地址,后续会详细说明。

    4、直接删除指定的节点

    1. void delete_node_1(struct test *p)
    2. {
    3. if(p->next==NULL) {
    4. printf("node end!\n");
    5. exit(-1);
    6. }
    7. struct test *q = p->next;
    8. p->x = q->x;
    9. p->next = q->next;
    10. free(q);
    11. }

    可以通过->next->next的方式或者循环,其实和第一个删除函数类似,只不过它只能手动的去设备

    比如删除第三个节点,假设头节点为head那么可以写成如下的形式,delete_node_1(head->next->next);

    5、从前到后的顺序添加一个新的节点

    1. void add_node_f(struct test *h,int n)
    2. {
    3. int i;
    4. struct test *temp = h;
    5. for(i=0;i
    6. temp=temp->next;
    7. }
    8. struct test *Pnew = (struct test *)malloc(sizeof(struct test));
    9. Pnew->x=n;
    10. Pnew->next = temp->next ;
    11. temp->next = Pnew;
    12. }

    其实也非常的简单,通过for循环找到第n个节点,然后新建一个内存空间pnew将其插入到指定的位置。

    6、从后到前的顺序添加一个新的节点

    1. void add_node_b(struct test *b,int n)
    2. {
    3. int i;
    4. struct test *temp = b;
    5. struct test *Pnew = (struct test *)malloc(sizeof(struct test));
    6. Pnew->x=node_nub-n;
    7. for(i=0;i
    8. temp=temp->last;
    9. }
    10. Pnew->next = temp->next ;
    11. temp->next = Pnew;
    12. }

    注意前面提到的node_nub这个全局变量,这个值即总的节点的值减去偏移的值n即为节点的id值不过这个值是会变化的最好是用一个线程来监视这个值

    7、main函数

    1. int main(void)
    2. {
    3. int i;
    4. struct test *head=NULL;
    5. struct test *tail=NULL;
    6. struct test *prev,*current;
    7. for(i=0;i<10;i++){
    8. current=(struct test*)malloc(sizeof(struct test));
    9. if(head==NULL)
    10. head=current;
    11. else
    12. prev->next = current;
    13. current->last = prev;
    14. current->next = NULL;
    15. current->x=i;
    16. prev=current;
    17. }
    18. tail = current;
    19. prev = tail;
    20. current = head;
    21. while(current!=NULL){
    22. node_nub++;
    23. current = current->next;
    24. }
    25. current = head;
    26. // delete_node_1(tail->last->last->next);
    27. add_node_f(head,2);
    28. delete_node_f(head,2);
    29. add_node_b(tail,6);
    30. delete_node_b(tail,6);
    31. // delete_node_b(tail,6);
    32. while(current!=NULL){
    33. printf("x=%d\n",current->x);
    34. current = current->next;
    35. }
    36. return 0;
    37. }

    main函数首先初始化四个结构体用for循环创建10个节点,每个节点都有指向下一个节点的next和上一个节点的last,完成后current指针正好在尾部所以用tail将current的值保存下来作为尾部节点的地址,将current指向首部然后获取节点个数然后调用上述的四个函数最后打印出来结果。

  • 相关阅读:
    初识数据结构
    235 设置Shell脚本开机自启
    艾美捷CY7标记链霉亲和素的功能和应用价值
    Dubbo捕获自定义异常问题
    vue 父子孙页面传值的多种方法
    什么是神经网络,它们是如何工作的?(神经网络架构基本指南)
    Java————数组
    css实现一个炫酷动画loading(四)
    C++文件加密、解密
    Code For Better 谷歌开发者之声——我与Android同成长
  • 原文地址:https://blog.csdn.net/qq_29734297/article/details/126280360