反转单链表的两种方法
今天看了帅地的第二版资料,突然发现单链表的反转居然还可以用递归来做,太妙了吧!
直接上代码,目前只有C++版的(用指针写链表它不香吗?):
// 递归法反转单链表
ListNode* reverseListPlus(ListNode* pHead){
if(pHead == nullptr || pHead->next == nullptr)
return pHead;
ListNode* reverseNode = reverseListPlus(pHead->next);
pHead->next->next = pHead;
pHead->next = nullptr;
return reverseNode;
}
int main()
{
ListNode* pNode1 = createListNode(1);
ListNode* pNode2 = createListNode(2);
ListNode* pNode3 = createListNode(3);
ListNode* pNode4 = createListNode(4);
ListNode* pNode5 = createListNode(5);
connectListNodes(pNode1, pNode2);
connectListNodes(pNode2, pNode3);
connectListNodes(pNode3, pNode4);
connectListNodes(pNode4, pNode5);
PrintListNodes(pNode1);
// 递归法反转链表
reverseListPlus(reverseList(pNode1));
// 测试反转是否成功
PrintListNodes(pNode5);
return 0;
}
代码解释:
1、ListNode* reverseNode = reverseListPlus(pHead->next);
-
递归法的目的是要返回一个新的头节点,这个新的头节点是原来链表的尾节点。
-
递归是方法自己调用自己,栈的特性是先进后出、后进先出。所以这段代码的作用是不断的去压栈。
2、pHead->next->next = pHead;
把当前节点指向的下一个节点的指向变为自己。(不要慌,这段代码的解释,下面有图有真相);
3、pHead->next = nullptr;
当前节点指向的下一个节点变为空。
是不是看了上面的解释还有点不理解,别急,我第一次看这段代码的时候也是懵逼的(内心wc:这写了个啥,怎么就反转链表了),要理解这段代码首先,我们得去压几个栈:
ListNode* reverseNode = reverseListPlus(pHead->next);
这段代码会执行四次,压栈四次,如图:
if(pHead == nullptr || pHead->next == nullptr) return pHead;
这段代码会让 reverseListPlus(pHead(4)) 发生弹栈,然而链表没有发生任何变化。。。方法继续执行。
接着 reverseRecursion(head(3)) 弹栈执行下面这段代码
head.next.next = head;
head.next = null;
reverseRecursion(head(3))
执行之后链表发生了如下变化:
持续到最后reverseRecursion(head(1))出栈:链表反转完成,撒花
head.next.next = head;
head.next = null;