算法练习-反转一个单链表(思路+流程图+代码)

难度参考

        难度:简单

        分类:链表

        难度与分类由我所参与的培训课程提供,但需要注意的是,难度与分类仅供参考。以下内容均为个人笔记,旨在督促自己认真学习。

题目

        反转一个单链表(不带头节点)
        示例1:
        输入:1->2->3->4->5->null
        输出:5->4->3->2->1->null
        解释:链表反转后顺序逆序,由1->2->3->4->5->null,变成了5->4->3->2->1->null

思路

        初始化两个指针:prevcurrent,分别指向当前节点的前一个节点和当前节点。

  1. 使用一个临时指针 nextNode 保存当前节点的下一个节点,以备后续使用。
  2. 在循环中,将当前节点的 next 指针指向 prev,实现反转操作。
  3. 移动 prevcurrent 指针,继续向后遍历链表。
  4. 重复步骤 3 和 4,直到 current 指针指向链表末尾,即 currentNULL
  5. 返回反转后的链表的头节点,即原链表的末尾节点

算法练习-反转一个单链表(思路+流程图+代码)_第1张图片

算法练习-反转一个单链表(思路+流程图+代码)_第2张图片

算法练习-反转一个单链表(思路+流程图+代码)_第3张图片

示例

        理解链表反转可能有些抽象,但可以通过将其拆分成简单的步骤来理解。以下是更具体的步骤和示例,帮助你更好地理解链表反转:

        假设我们有一个链表:1 -> 2 -> 3 -> 4 -> 5 -> null

  1. 初始化两个指针,prevcurrent,初始时都指向 null
  2. 从链表的头部开始遍历,首先处理节点 1
    • prev 指向 null
    • current 指向 1
  3. 在每一步中,我们将 currentnext 指向 prev,即将 1 -> null 变成 1 <- null,然后移动指针:
    • prev 指向 1
    • current 指向 2
  4. 重复上述步骤,将每个节点的 next 指向前一个节点,直到到达链表末尾:
    • prev 指向 4
    • current 指向 5
  5. 最终,链表变成:5 -> 4 -> 3 -> 2 -> 1 -> null

        通过不断将当前节点的 next 指向前一个节点,我们逐步完成了链表的反转。这是链表反转的基本思路。希望这个示例有助于你更好地理解这个过程。

梳理

  1. 首先,我们定义了一个单链表节点结构 ListNode,其中包括一个整数值 val 用于存储节点的值,以及一个指向下一个节点的指针 next

  2. 然后,定义了一个 reverseList 函数,它接受一个头节点 head 作为参数,用于反转单链表。

  3. reverseList 函数中,我们初始化了两个指针 prevcurrent,开始时都指向 NULLprev 用于存储当前节点的前一个节点,而 current 用于表示当前节点。

  4. 使用 while 循环遍历链表,循环条件是 current != NULL,即遍历链表直到当前节点为空(链表末尾)。

  5. 在每次循环中,我们首先保存下一个节点的指针为 nextNode,以备后续使用。

  6. 然后,将当前节点的 next 指针指向前一个节点 prev,这样就完成了当前节点指向前一个节点的反转操作。

  7. 接着,将 prev 指针移动到当前节点,为下一轮循环做准备。

  8. 最后,将 current 指针移动到下一个节点 nextNode,继续下一轮循环。

  9. 当循环结束时,prev 指针指向原链表的末尾节点,即反转后的链表的头节点,因此我们返回 prev 作为反转后链表的新头节点。

  10. main 函数中,我们创建了一个示例链表,然后调用 printList 函数打印原始链表,再调用 reverseList 函数进行链表反转,最后再次调用 printList 函数打印反转后的链表。

算法练习-反转一个单链表(思路+流程图+代码)_第4张图片

代码

#include 

using namespace std;

// 定义单链表节点结构
struct ListNode {
    int val;           // 存储节点的值
    ListNode* next;    // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 构造函数,初始化节点的值和指针
};

// 反转单链表的函数
ListNode* reverseList(ListNode* head) {
    ListNode* prev = NULL;      // 初始化前一个节点为NULL,用于存储当前节点的前一个节点
    ListNode* current = head;   // 初始化当前节点为头节点,从头节点开始反转

    while (current != NULL) {   // 循环遍历链表,直到当前节点为NULL(即链表末尾)
        ListNode* nextNode = current->next;  // 保存下一个节点的指针,以备后续使用
        current->next = prev;                // 反转当前节点的指针方向,使其指向前一个节点
        prev = current;                     // 移动prev指针,指向当前节点,为下一轮循环做准备
        current = nextNode;                 // 移动current指针,指向下一个节点,继续反转操作
    }

    return prev;  // 返回新的头节点,即原链表的末尾节点
}

// 打印链表的函数
void printList(ListNode* head) {
    ListNode* current = head;  // 从头节点开始遍历链表
    while (current != NULL) {  // 循环遍历链表,直到当前节点为NULL
        cout << current->val << " ";  // 打印当前节点的值
        current = current->next;      // 移动到下一个节点
    }
    cout << "null" << endl;  // 打印链表末尾的null表示链表结束
}

int main() {
    // 创建示例链表:1->2->3->4->5->null
    ListNode* head = new ListNode(1);  // 创建头节点并初始化值为1
    head->next = new ListNode(2);      // 创建下一个节点并初始化值为2
    head->next->next = new ListNode(3); // 创建下一个节点并初始化值为3
    head->next->next->next = new ListNode(4);  // 创建下一个节点并初始化值为4
    head->next->next->next->next = new ListNode(5);  // 创建下一个节点并初始化值为5

    cout << "原始链表:" << endl;
    printList(head);  // 打印原始链表

    // 反转链表
    ListNode* reversedHead = reverseList(head);  // 调用反转函数

    cout << "反转后的链表:" << endl;
    printList(reversedHead);  // 打印反转后的链表

    return 0;
}

        时间复杂度:O(n)
        空间复杂度:O(1)

打卡

算法练习-反转一个单链表(思路+流程图+代码)_第5张图片

你可能感兴趣的:(算法编程笔记,算法,流程图,数据结构,c++)