颠倒一个链表的顺序

来源:互联网 发布:交行中铁网络信用卡 编辑:程序博客网 时间:2024/06/10 00:15

对于颠倒一个链表的顺序这里我们介绍两种可行的方法: 递归的和非递归的.


我们先说说递归的方法:

(1)如果一个链表为空链表,那么他的逆序还是为空,也就是这个链表本身了.

(2)如果一个链表中只有一个节点,那么他的逆序就是这个链表本身.

(3)如果一个链表的长度大于一,那么我们做如下递归.

把当前链表的除了头节点(head)之外的剩余节点组成的链表逆序,也就是递归调用,并得到剩余链表逆序后的头结点(ph),

此时将head的下一个节点的的next指向head, 并将head的next指针置空.然后返回ph.


说起来比较抽象,画图模拟一下吧:

(1).(2)点很简单,我们只说(3):


我们调用函数reverse(head), 将整个链表的头部传进去.然后head不为空,且head.next不为空,那么递归调用,reverse(head.next),此时链表长度减一.程序一直递归,直至当前传入的链表长度为1时,程序返回该子链表本身,其实就只有一个节点,也就是原链表的最后一个节点,此时程序返回ph(就是唯一的那个节点)到上一次调用处,此时程序处在倒数第二层调用.情况如下

图中的ph就是最后一次递归返回的节点,head为倒数第二次递归时链表的头结点.此时如何完成节点顺序的倒置呢,如下:


该过程分为两步: 

第一步先是将head的后一个节点的next指向当前头结点.

第二部再是将head的next置为空,去掉head.next和ph之间的关系.

此时的链表变为:


然后倒数第二层递归执行完成,将ph返回给倒数第三层.情形如下:


图中框起来部分就是倒数第二层递归时已经完成逆序的部分,当前递归中应该处理此时的head与ph之间的关系

此时依然完成上面已经提到过的那两步:


此时绿线部分便是在此次循环过程中完成的工作,一次类推.直至将整个链表逆序.


程序源码:

public Node reverse(Node head){if (head == null){return head;}if (head.next == null){return head;}Node ph = reverse(head.next);head.next.next = head;head.next = null;return ph;}


下面我们来说说非递归的方法:

非递归过程比较简单,此处仅给出实现代码:

public Node reverse1(Node head){if (head == null){return null;}Node p = head;Node previous = null;while (p.next != null){p.next = previous;previous = p;p = previous.next;}p.next = previous;return p;}

整个过程中使用previous保存已经处理过的上一个节点,总是将当前节点的next指向上一个节点.而上一个节点恰恰就是原链表中当前节点的下一个节点,以此来实现链表的颠倒.

注意事项为头结点的上一个节点为空,因此previous应该初始化为空,还有一点就是原链表的尾会成为新链表的头,而原链表的尾部的next为空,因此需要单独处理,也就是在推出循环后,将p.next指向previous.

0 0