• 链表逆序用哨兵位头节点


    在C语言中实现链表的逆序,使用哨兵头节点是一种常见的做法。哨兵头节点可以简化代码逻辑,特别是当链表为空时,可以避免空指针异常。下面是一个使用哨兵头节点逆序单链表的C语言实现

    示例:

    1. #include
    2. #include
    3. // 定义链表节点结构体
    4. typedef struct ListNode {
    5. int val;
    6. struct ListNode *next;
    7. } ListNode;
    8. // 创建新节点
    9. ListNode* createNode(int value) {
    10. ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    11. if (!newNode) {
    12. exit(-1); // 分配内存失败,退出程序
    13. }
    14. newNode->val = value;
    15. newNode->next = NULL;
    16. return newNode;
    17. }
    18. // 逆序链表,使用哨兵头节点
    19. void reverseList(ListNode** headRef) {
    20. ListNode* prev = NULL;
    21. ListNode* current = *headRef;
    22. ListNode* next = NULL;
    23. while (current != NULL) {
    24. next = current->next; // 保存下一个节点
    25. current->next = prev; // 当前节点指向前一个节点,实现逆序
    26. prev = current; // 前一个节点移动到当前节点
    27. current = next; // 当前节点移动到下一个节点
    28. }
    29. *headRef = prev; // 更新头节点
    30. }
    31. // 打印链表
    32. void printList(ListNode* head) {
    33. ListNode* temp = head;
    34. while (temp != NULL) {
    35. printf("%d ", temp->val);
    36. temp = temp->next;
    37. }
    38. printf("\n");
    39. }
    40. // 主函数,测试逆序链表功能
    41. int main() {
    42. ListNode* head = createNode(1);
    43. head->next = createNode(2);
    44. head->next->next = createNode(3);
    45. head->next->next->next = createNode(4);
    46. printf("原始链表:");
    47. printList(head);
    48. reverseList(&head);
    49. printf("逆序后链表:");
    50. printList(head);
    51. // 释放链表内存
    52. ListNode* temp;
    53. while (head != NULL) {
    54. temp = head;
    55. head = head->next;
    56. free(temp);
    57. }
    58. return 0;
    59. }

    在这个代码中,我们首先定义了链表节点的结构体ListNode,然后提供了创建新节点的函数createNodereverseList函数用来逆序链表,它使用了一个哨兵头节点,即第一个节点作为prev指针的初始位置,最后将头节点更新为prev指针所指向的节点。printList函数用来打印链表的节点值。

    main函数中,我们创建了一个简单的链表,并调用reverseList函数进行逆序,然后打印出逆序后的结果。最后,我们释放了链表占用的内存。

    请注意,在实际的项目开发中,还需要对代码进行适当的错误处理和边界条件检查,以确保程序的健壮性。

    在C语言中,使用哨兵位头节点(dummy head)来逆序链表是一种常见的技巧,因为它可以简化边界条件的处理。以下是一个使用哨兵位头节点逆序单链表的示例代码:

    // 链表节点的结构体定义

    1. typedef struct ListNode {
    2. int val;
    3. struct ListNode *next;
    4. } ListNode;

    // 创建一个新的链表节点

    1. ListNode* createNode(int value) {
    2. ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    3. if (!newNode) {
    4. exit(-1); // 分配内存失败,退出程序
    5. }
    6. newNode->val = value;
    7. newNode->next = NULL;
    8. return newNode;
    9. }

    // 在链表的末尾添加一个新节点

    1. void appendNode(ListNode** headRef, int value) {
    2. ListNode* newNode = createNode(value);
    3. ListNode* temp = *headRef;
    4. if (temp == NULL) {
    5. *headRef = newNode;
    6. return;
    7. }
    8. while (temp->next != NULL) {
    9. temp = temp->next;
    10. }
    11. temp->next = newNode;
    12. }

    // 逆序链表,使用哨兵位头节点

    1. void reverseList(ListNode** headRef) {
    2. ListNode* prev = NULL;
    3. ListNode* current = *headRef;
    4. ListNode* next = NULL;
    5. while (current != NULL) {
    6. next = current->next; // 保存下一个节点
    7. current->next = prev; // 当前节点指向前一个节点
    8. prev = current; // 前一个节点移动到当前节点
    9. current = next; // 当前节点移动到下一个节点
    10. }
    11. *headRef = prev; // 更新头节点
    12. }

    // 打印链表

    1. void printList(ListNode* head) {
    2. ListNode* temp = head;
    3. while (temp != NULL) {
    4. printf("%d ", temp->val);
    5. temp = temp->next;
    6. }
    7. printf("\n");
    8. }

    // 主函数,测试逆序链表功能

    1. int main() {
    2. ListNode* head = NULL; // 哨兵位头节点
    3. // 向链表中添加元素
    4. appendNode(&head, 1);
    5. appendNode(&head, 2);
    6. appendNode(&head, 3);
    7. appendNode(&head, 4);
    8. printf("原始链表:");
    9. printList(head);
    10. // 逆序链表
    11. reverseList(&head);
    12. printf("逆序后链表:");
    13. printList(head);
    14. // 释放链表内存
    15. ListNode* temp;
    16. while (head != NULL) {
    17. temp = head;
    18. head = head->next;
    19. free(temp);
    20. }
    21. return 0;
    22. }

    总代码

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. // 链表节点的结构体定义
    4. typedef struct ListNode {
    5. int val;
    6. struct ListNode *next;
    7. } ListNode;
    8. // 创建一个新的链表节点
    9. ListNode* createNode(int value) {
    10. ListNode* newNode = (ListNode*)malloc(sizeof(ListNode));
    11. if (!newNode) {
    12. exit(-1); // 分配内存失败,退出程序
    13. }
    14. newNode->val = value;
    15. newNode->next = NULL;
    16. return newNode;
    17. }
    18. // 在链表的末尾添加一个新节点
    19. void appendNode(ListNode** headRef, int value) {
    20. ListNode* newNode = createNode(value);
    21. ListNode* temp = *headRef;
    22. if (temp == NULL) {
    23. *headRef = newNode;
    24. return;
    25. }
    26. while (temp->next != NULL) {
    27. temp = temp->next;
    28. }
    29. temp->next = newNode;
    30. }
    31. // 逆序链表,使用哨兵位头节点
    32. void reverseList(ListNode** headRef) {
    33. ListNode* prev = NULL;
    34. ListNode* current = *headRef;
    35. ListNode* next = NULL;
    36. while (current != NULL) {
    37. next = current->next; // 保存下一个节点
    38. current->next = prev; // 当前节点指向前一个节点
    39. prev = current; // 前一个节点移动到当前节点
    40. current = next; // 当前节点移动到下一个节点
    41. }
    42. *headRef = prev; // 更新头节点
    43. }
    44. // 打印链表
    45. void printList(ListNode* head) {
    46. ListNode* temp = head;
    47. while (temp != NULL) {
    48. printf("%d ", temp->val);
    49. temp = temp->next;
    50. }
    51. printf("\n");
    52. }
    53. // 主函数,测试逆序链表功能
    54. int main() {
    55. ListNode* head = NULL; // 哨兵位头节点
    56. // 向链表中添加元素
    57. appendNode(&head, 1);
    58. appendNode(&head, 2);
    59. appendNode(&head, 3);
    60. appendNode(&head, 4);
    61. printf("原始链表:");
    62. printList(head);
    63. // 逆序链表
    64. reverseList(&head);
    65. printf("逆序后链表:");
    66. printList(head);
    67. // 释放链表内存
    68. ListNode* temp;
    69. while (head != NULL) {
    70. temp = head;
    71. head = head->next;
    72. free(temp);
    73. }
    74. return 0;
    75. }

    在这个代码中,我们首先定义了链表节点的结构体ListNode。然后,我们提供了创建新节点和向链表末尾添加新节点的函数createNodeappendNodereverseList函数用来逆序链表,它使用了一个哨兵头节点prev,并最终将头节点更新为prev指针所指向的节点。printList函数用来打印链表的节点值。

    main函数中,我们创建了一个链表,并调用reverseList函数进行逆序,然后打印出逆序后的结果。最后,我们释放了链表占用的内存。

    请注意,在实际的项目开发中,还需要对代码进行适当的错误处理和边界条件检查,以确保程序的健壮性。

  • 相关阅读:
    Linux工具(一)
    【React入门实战】实现Todo代办
    vue3项目安装eslint和prettier
    k8s审计
    Apache commons exec框架的简介说明
    数组问题之《两数之和》以及《三数之和 》
    Qt5开发从入门到精通——第三篇(窗口篇——分割窗口)
    某网书籍信息爬虫
    【python中级】裁剪1、2寸电子照片
    数电学习(十、脉冲波形的产生和整形)(一)
  • 原文地址:https://blog.csdn.net/2401_83427936/article/details/139371365