• 单链表翻转


    首先参考博客 看图理解单链表的反转 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);
    
        }
    
    }
  • 相关阅读:
    图书管理系统时序图和活动图
    图书管理用例图
    课堂练习(团队)
    课堂练习(RASCI模型)
    课堂练习(分析设想app)
    课堂练习(NABCD model)
    课堂练习(问答题)
    测试用例
    课堂练习(测试计划)
    错误报告
  • 原文地址:https://www.cnblogs.com/chengpeng15/p/9360260.html
Copyright © 2020-2023  润新知