单链表翻转

首先参考博客 看图理解单链表的反转 https://blog.csdn.net/feliciafay/article/details/6841115(c语言版本,并含有详细图解)

 

链表翻转的图文讲解(递归与迭代两种实现)

如何把一个单链表进行反转?

方法1:将单链表储存为数组,然后按照数组的索引逆序进行反转。

方法2:使用3个指针遍历单链表,逐个链接点进行反转。

方法3:从第2个节点到第N个节点,依次逐节点插入到第1个节点(head节点)之后,最后将第一个节点挪到新表的表尾。

方法4:   递归(相信我们都熟悉的一点是,对于树的大部分问题,基本可以考虑用递归来解决。但是我们不太熟悉的一点是,对于单链表的一些问题,也可以使用递归。可以认为单链表是一颗永远只有左(右)子树的树,因此可以考虑用递归来解决。或者说,因为单链表本身的结构也有自相似的特点,所以可以考虑用递归来解决)

 

 

 

参考 1  https://blog.csdn.net/feliciafay/article/details/6841115(c语言版本,并含有详细图解)

参考 2 Java单链表反转 Java实现单链表翻转 https://blog.csdn.net/guyuealian/article/details/51119499

参考 3 经典算法——单链表反转的递归方法和非递归方法 https://blog.csdn.net/geekmanong/article/details/51097196

 

Node 定义

 

 

package single_list;

/**
 * Created by bjchengpeng on  2018/7/24.
 */
public class Node {
    private int Data;
    private Node next;

    public Node(int Data) {
        this.Data = Data;
    }

    public int getData() {
        return Data;
    }

    public void setData(int data) {
        Data = data;
    }

    public Node getNext() {
        return next;
    }

    public void setNext(Node next) {
        this.next = next;
    }

    @Override
    public String toString() {
        return "Node{" +
                "Data=" + Data +
                ", next=" + next +
                '}';
    }
}

 

 

 

 考虑一个结点的情况,直接打印出来。

同时再次注意下java 引用传递,别写错 

下面是非递归写法

package single_list;

/**
 * Created by bjchengpeng on  2018/7/24.
 */
public class ReverseList {
    public static void main(String[] args) {

        Node head = iniList();
        printListNode(head);
//        下面两行是没有理解java引用传递,传递的是个副本,副本又重新分配空间
//        revertWithNonRecursive(head);
//        printListNode(head);

        Node revertNode = revertWithNonRecursive(head);
        printListNode(revertNode);
    }

    private static Node iniList() {
//        Node head = new Node(0);
//        Node node1 = new Node(1);
//        Node node2 = new Node(2);
//        Node node3 = new Node(3);


        Node head = new Node(4);
        Node node1 = new Node(3);
        Node node2 = new Node(7);
        Node node3 = new Node(9);
        head.setNext(node1);
        node1.setNext(node2);
        node2.setNext(node3);

        return head;
    }

    public static Node revertWithNonRecursive(Node head) {
        if (head == null || head.getNext() == null) {
            return head;
        }

        Node cur = head.getNext();
        head.setNext(null);//第一个节点变成尾节点,指向null


//        下面是大于1个节点的情况
        while (cur != null) {

            Node temp = cur.getNext();
            cur.setNext(head);
            head = cur;
            cur = temp;
        }
        return head;
    }

    private static void printListNode(Node head) {
        while (head != null) {
            System.out.print(head.getData() + " ");
            head = head.getNext();
        }
        System.out.println();
    }
}

 

递归实现

递归方式
  我们再来看看递归实现链表翻转的实现,前面非递归方式是从前面数1开始往后依次处理,而递归方式则恰恰相反,它先循环找到最后面指向的数5,然后从5开始处理依次翻转整个链表。
  首先指针H迭代到底如下图所示,并且设置一个新的指针作为翻转后的链表的头。由于整个链表翻转之后的头就是最后一个数,所以整个过程NewH指针一直指向存放5的地址空间。

 

 上面的图不对,改为下面。可以从程序中是(4.next)就开始返回了

 

 


  然后H指针逐层返回的时候依次做下图的处理,将H指向的地址赋值给H->next->next指针,并且一定要记得让H->next =NULL,也就是断开现在指针的链接,否则新的链表形成了环,下一层H->next->next赋值的时候会覆盖后续的值。

 

 

  继续返回操作:

 

  上图第一次如果没有将存放4空间的next指针赋值指向NULL,第二次H->next->next=H,就会将存放5的地址空间覆盖为3,这样链表一切都大乱了。接着逐层返回下去,直到对存放1的地址空间处理。

 

 

  返回到头:

 


上面的图参考:

链表翻转的图文讲解(递归与迭代两种实现)

 

package StackMin.ReverseList_offer16;


public class Solution1 {
    public ListNode ReverseList(ListNode head) {
        // head看作是前一结点,head.getNext()是当前结点,reHead是反转后新链表的头结点
        if (head == null || head.next == null) {
            return head;// 若为空链或者当前结点在尾结点,则直接还回
        }
        ListNode reHead = ReverseList(head.next);// 先反转后续节点head.getNext()
        head.next.next = head;// 将当前结点的指针域指向前一结点
        head.next = null;// 前一结点的指针域令为null;
        return reHead;// 反转后新链表的头结点
    }

    public static void main(String[] args) {
        ListNode head = new ListNode(1);
        ListNode L2 = new ListNode(2);
        ListNode L3 = new ListNode(3);
        ListNode L4 = new ListNode(4);
        ListNode L5 = new ListNode(5);
        head.next = L2;
        L2.next = L3;
        L3.next = L4;
        L4.next = L5;
        ListNode k = new Solution1().ReverseList(head);
        System.out.println(k.val);

    }

}

 

posted @ 2018-07-24 15:28  鹏鹏进阶  阅读(250)  评论(0编辑  收藏  举报