链表原地翻转(c++版)
链表原地反转模式可在不使用额外空间的情况下,反转链表的部分节点。
当你需要反转链表的某些部分时,可使用该模式。
【Leetcode206】反转链表

过程:需要三个指针,使用了迭代的做法;当然还有递归的方法,但不太容易理解
核心代码:
q=p;//指向前一个
p=q;q=r;r=r->next;//三个指针都跳到下一个
注意临界条件,当操作完成时,q和r指向nullptr,而p正好指向最后一个操作的节点,应该返回p即可。

代码中用prev\curr\nextTemp分别代替p\q\r,从用户输入端接收数据(-1为结束输入的标志),创建链表,然后再进行反转。
#include <iostream>
using namespace std;
// 定义链表节点结构
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
// 反转链表的迭代实现
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr; // 前一个节点
ListNode* curr = head; // 当前节点
while (curr != nullptr) {
ListNode* nextTemp = curr->next; // 保存下一个节点
curr->next = prev; // 反转当前节点的指向
prev = curr; // 移动 prev 到当前节点
curr = nextTemp; // 移动 curr 到下一个节点
}
return prev; // 返回新的头节点
}
};
// 打印链表
void printList(ListNode* head) {
ListNode* current = head;
while (current != nullptr) {
cout << current->val << " ";
current = current->next;
}
cout << endl;
}
// 接收输入并创建链表
ListNode* createList() {
ListNode* head = nullptr; // 链表头节点
ListNode* tail = nullptr; // 链表尾节点
int value;
cout << "请输入链表节点的值(以 -1 结束输入):" << endl;
while (true) {
cin >> value;
if (value == -1) { // 输入 -1 结束
break;
}
// 创建新节点
ListNode* newNode = new ListNode(value);
if (head == nullptr) { // 如果链表为空,新节点作为头节点
head = newNode;
tail = newNode;
} else { // 否则将新节点添加到链表尾部
tail->next = newNode;
tail = newNode;
}
}
return head; // 返回链表的头节点
}
int main() {
// 创建链表
ListNode* head = createList();
cout << "原始链表: ";
printList(head);
// 反转链表
Solution solution;
ListNode* reversedHead = solution.reverseList(head);
cout << "反转后的链表: ";
printList(reversedHead);
return 0;
}
递归方法:
ListNode* reverseList(ListNode* head) { // 递归终止条件:如果链表为空或者只有一个节点,直接返回该节点 if (head == nullptr || head->next == nullptr) { return head; } // 递归调用 reverseList 函数,反转从 head->next 开始的后续链表 ListNode* newHead = reverseList(head->next); // 将当前节点的下一个节点的 next 指针指向当前节点,实现局部反转 head->next->next = head; // 将当前节点的 next 指针置为 nullptr,避免形成循环 head->next = nullptr; // 返回反转后链表的头节点 return newHead; }
【Leetcode92】部分连续地方反转
分析:部分链中反转(2、3、4)加上头尾两节点的处理2的指针域和指向4的指针。所以考虑在上个题的基础上,标记变换的连续链表两边节点以及与之相邻的两个节点:(共四个p1->1;p2->2;q1->4;1q2->5)

反转之外的部分:p1->next=q1;p2->next=q2
反转之内(L=p2,r=q1)的跟上个题目一样,改一下遍历开始和结束的位置即可
注意:当 L为 1 时,也就是要反转的区间从链表头节点开始,此时
p1为空指针,需要特殊处理。建立一个虚拟头节点dummy,这样就能避免处理 L 为 1 时的边界情况。也就是建立一个空的头结点。
class Solution {
public:
// 反转从 p2 到 q1 之间的链表
ListNode* reverseAllList(ListNode* p2, ListNode* q1) {
ListNode* p = nullptr; // 前一个节点
ListNode* curr = p2; // 当前节点
while (curr != q1) {
ListNode* nextTemp = curr->next; // 保存下一个节点
curr->next = p; // 反转当前节点的指向
p = curr; // 移动 p 到当前节点
curr = nextTemp; // 移动 curr 到下一个节点
}
return p; // 返回新的头节点
}
// 反转链表中从第 l 个节点到第 r 个节点的部分
ListNode* linkList(ListNode* head, int l, int r) {
if (l == r) return head; // 如果 l 和 r 相等,无需反转
ListNode dummy(0);//建立一个空的头结点
dummy.next = head;
ListNode* p1 = &dummy; // 指向第 l-1 个节点
ListNode* p2 = nullptr; // 指向第 l 个节点
ListNode* q1 = nullptr; // 指向第 r 个节点
ListNode* q2 = nullptr; // 指向第 r+1 个节点
// 找到第 l-1 个节点
for (int i = 1; i < l; ++i) {
p1 = p1->next;
}
p2 = p1->next;
// 找到第 r 个节点
q1 = p2;
for (int j = l; j < r; ++j) {
q1 = q1->next;
}
q2 = q1->next;
// 反转从 p2 到 q1 之间的链表
p1->next = reverseAllList(p2, q2);
p2->next = q2;
return dummy.next;
}
};
【Leetcode24】两两交换链表中的节点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

思考与转化:很像2个元素交换(需要引入一个新变量),不过这次交换的是位置。
初始化temp:
ListNode* temp = new ListNode(0); temp->next = head;
核心变化:
temp->node2;// temp->next = node2
node1->node3;// node1->next = node2->next
node2->node1;// node2->next = node1;
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
// 创建虚拟头节点,方便处理头节点交换的情况
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
// temp 指针用于遍历链表并控制交换操作
ListNode* temp = dummyHead;
// 当 temp 后面至少还有两个节点时,进行交换操作
while (temp->next != nullptr && temp->next->next != nullptr) {
// 标记要交换的两个节点
ListNode* node1 = temp->next;
ListNode* node2 = temp->next->next;
// 进行节点交换操作
temp->next = node2;
node1->next = node2->next;
node2->next = node1;
// temp 指针移动到交换后这一对节点的末尾位置,为下一次交换做准备
temp = node1;
}
// 获取交换后的链表头节点
ListNode* ans = dummyHead->next;
// 释放虚拟头节点的内存
delete dummyHead;
return ans;
}
};
提醒:遇到链表就画图
更多推荐
所有评论(0)