单链表反转,就是将链表中所有节点的指向改变方向,具体可以有四种方式。
迭代法
迭代法的思想很直接,每次改变一个节点的next指向,依次迭代到尾节点。
需要3个辅助节点:beg,mid,end
每次将mid指向beg,然后beg, mid, end整体向后移动一个单位,直到完成反转。
1 | ListNode* reverseList(ListNode* head) { |
递归法
递归法的思想跟迭代法正好相反,且不易理解。从尾链表开始依次向前遍历,过程中改变每个节点的指向。
先给出代码,再做解释:
1 | ListNode* reverseList(ListNode* head){ |
每次执行到new_node处时,都会深入链表一步,直到head->next==NULL
时才不继续深入,此时返回的是链表反转之后的新头节点,并且该节点作为每步递归的返回值,一直在不断地向上层递归返回。
在过程中的操作可以用下面的简图来表示,1,2步分别代表着 head->next->next=head
以及 head->next=NULL
。
再一次返回上层时,new_head仍然是4号节点,但是把3的next指向到2。
依次向上层返回,过程中不断修改节点指向,从而完成链表反转。
头插法
头插法的思路也比较简单,设置一个哑节点
,然后迭代地将链表中的节点插入到哑节点后,最后返回哑节点的next节点。
构建哑节点:
将1节点插入到哑节点后:
这样也很容易写出代码:
1 | ListNode* reverseList(ListNode* head){ |
原地置换法
所谓原地,就是直接对原链表进行修改。在过程中需要借助两个指针 beg 和 end。
过程可以参考简图:
代码如下:
1 | ListNode* reverseList(ListNode* head){ |
以上四种方法建议熟记!!