链表的中间段逆置跟链表的逆置的核心思想是一致的,只不过链表的中间段逆置不一定是从头结点开始逆置或者不一定逆置到链表的最后一个节点,即只逆置中间的一部分结点。实现链表的中间段逆置,要找到逆置段的开始节点、该节点的前驱元、逆置段的尾节点、逆置段尾节点的后一个节点,在逆置中间段用就地逆置法或者头插法实现中间段逆置,然后逆置段的前一段、逆置段、逆置段的后一段连接起来,这样就是实现了链表中间段的逆置。
下面用7个节点的链表演示具体的过程
以上过程的代码实现如下:
//实现链表的中间段逆置
#include<iostream>
struct ListNode {
int value;
ListNode* nextNode;
ListNode(int x) :value(x), nextNode(NULL) { }
};
class Solution {
public:
ListNode* ReverseBetween(ListNode* head, int m, int n) {
ListNode* result = head;//返回结果
ListNode* pre_head = NULL;//逆置段的前驱元
int chage_num = n - m + 1;//中间逆置段的节点数
while (head && --m) {//将头指针移动到逆置段的头结点,并寻找逆置段的前驱元
pre_head = head;
head = head->nextNode;
}
ListNode* modify_list_tail = head;
ListNode* new_head = NULL;
while (chage_num>0) {//用就地拆解法逆置中间段
ListNode* next = head->nextNode;
head->nextNode = new_head;
new_head = head;
head = next;
chage_num--;
}
modify_list_tail->nextNode = head;//将逆置中间段的最后一个结点与逆置段的后一个节点相连
if (pre_head) {//不是从头结点开始逆置
pre_head->nextNode = new_head;
}
else {//从头结点开始逆置
result = new_head;
}
return result;
}
};
void printList(ListNode* head, const char* list_name) {
printf("%s:", list_name);
if (!head) {
printf("NULL\n");
return;
}
while (head) {
printf("[%d] ", head->value);
head = head->nextNode;
}
printf("\n");
}
int main() {
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
ListNode f(6);
ListNode g(7);
ListNode* head = &a;
a.nextNode = &b;
b.nextNode = &c;
c.nextNode = &d;
d.nextNode = &e;
e.nextNode = &f;
f.nextNode = &g;
g.nextNode = NULL;
printList(head, "new");
Solution solve;
int m = 3, n = 5;
printList(solve.ReverseBetween(head,m,n), "old");
return 0;
}