????????难度:简单
????????分类:链表
????????难度与分类由我所参与的培训课程提供,但需要注意的是,难度与分类仅供参考。以下内容均为个人笔记,旨在督促自己认真学习。
????????反转一个单链表(不带头节点)
????????示例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
????????初始化两个指针:prev
和 current
,分别指向当前节点的前一个节点和当前节点。
nextNode
保存当前节点的下一个节点,以备后续使用。next
指针指向 prev
,实现反转操作。prev
和 current
指针,继续向后遍历链表。current
指针指向链表末尾,即 current
为 NULL
。????????理解链表反转可能有些抽象,但可以通过将其拆分成简单的步骤来理解。以下是更具体的步骤和示例,帮助你更好地理解链表反转:
????????假设我们有一个链表:1 -> 2 -> 3 -> 4 -> 5 -> null
prev
和 current
,初始时都指向 null
。1
:
prev
指向 null
current
指向 1
current
的 next
指向 prev
,即将 1 -> null
变成 1 <- null
,然后移动指针:
prev
指向 1
current
指向 2
next
指向前一个节点,直到到达链表末尾:
prev
指向 4
current
指向 5
????????通过不断将当前节点的 next
指向前一个节点,我们逐步完成了链表的反转。这是链表反转的基本思路。希望这个示例有助于你更好地理解这个过程。
首先,我们定义了一个单链表节点结构 ListNode
,其中包括一个整数值 val
用于存储节点的值,以及一个指向下一个节点的指针 next
。
然后,定义了一个 reverseList
函数,它接受一个头节点 head
作为参数,用于反转单链表。
在 reverseList
函数中,我们初始化了两个指针 prev
和 current
,开始时都指向 NULL
。prev
用于存储当前节点的前一个节点,而 current
用于表示当前节点。
使用 while
循环遍历链表,循环条件是 current != NULL
,即遍历链表直到当前节点为空(链表末尾)。
在每次循环中,我们首先保存下一个节点的指针为 nextNode
,以备后续使用。
然后,将当前节点的 next
指针指向前一个节点 prev
,这样就完成了当前节点指向前一个节点的反转操作。
接着,将 prev
指针移动到当前节点,为下一轮循环做准备。
最后,将 current
指针移动到下一个节点 nextNode
,继续下一轮循环。
当循环结束时,prev
指针指向原链表的末尾节点,即反转后的链表的头节点,因此我们返回 prev
作为反转后链表的新头节点。
在 main
函数中,我们创建了一个示例链表,然后调用 printList
函数打印原始链表,再调用 reverseList
函数进行链表反转,最后再次调用 printList
函数打印反转后的链表。
#include <iostream>
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)