[链表]链表&寻找中间点&环形链表&反转链表

链表:

是一种物理储存结构上的非连续储存结构,数据元素的逻辑顺序是通过链表中的引用链接次序实现的。

 知道头节点便可以访问链表中的所有节点。

如下代码创建链表类,并访问:

package list;
public class List1 {

    public static void main(String[] args) {
        Node head = new Node(7);
        head.next = new Node(3);
        head.next.next = new Node(8);
        head.next.next.next = new Node(5);
        head.next.next.next.next = new Node(6);

        Node n = head;  //从头部节点开始访问
        while (n != null) {  //只要引用了节点就继续访问节点数据
            System.out.println(n.value);  //访问节点中的数据
            n = n.next;  //得到n后面的节点,保存到n
        }
    }



    static class Node {//链表类
        private int value;//节点数据
        private Node prev;
        private Node next;
        public Node(int value) {
            this.value = value;
        }
    }
}

访问中间节点:

通过两个变量,变量fast走一步,变量slow走两步以此求出中间值。

偶数情况求中间值过程:

奇数情况求中间值过程: 

 

 

代码如下: 

package list;
public class ZhongJianJieDian {

    public static void main(String[] args) {
        Node head = new Node(7);
        head.next = new Node(3);
        head.next.next = new Node(8);
        head.next.next.next = new Node(5);
        head.next.next.next.next = new Node(6);

        Node mid = middleNode(head);
        System.out.println(mid.value);

        //Node n = head;  //从头部节点开始访问
        //while (n != null) {  //只要引用了节点就继续访问节点数据
        //    System.out.println(n.value);  //访问节点中的数据
        //    n = n.next;  //得到n后面的节点,保存到n
        //}
    }

    private static Node middleNode(Node head) {
        Node fast = head; //快引用,引用头部节点
        Node slow = head; //慢引用,引用头部节点

        //fast在范围内并且它的下一个也不是null
        while (fast != null && fast.next != null) {//两种情况
            fast = fast.next.next; //fast向后引用下两个节点
            slow = slow.next; //slow向后引用下一个节点
        }

        return slow; //循环结束slow所引用的节点,就是中间节点
    }


    static class Node {
        private int value;
        private Node prev;
        private Node next;
        public Node(int value) {
            this.value = value;
        }
    }
}

环形链表:

将末位置引用链接一个位置形成一个环(注意:一个也可以形成环,自己链接自己)

同样通过两个变量,变量fast走一步,变量slow走两步,当两个值重合时便说明有环形。否则fast走到末尾结束便无环形。

有环形链表的情况:

 无环形链表的情况:

 

package list;

public class HuanXingLianBiao {
    public static void main(String[] args) {
        Node head = new Node(8);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(1);
        head.next.next.next.next = new Node(9);

        head.next.next.next.next.next = head.next; //形成环,从末尾节点应用前面的节点

        boolean b = hasCircle(head);
        System.out.println("是否有环:"+b);
    }

    /*
    思路: 用快慢指针,快指针每次移动两步,慢指针每次移动一步,
          如果移动过程中,快慢指针重合,就表示有环;
          如果快指针都移动结束,就表示没有环。

    1. 变量fast, slow,都引用头部节点
    2. 进入循环,执行条件:fast!=null,并且fast.next!=null
    3. fast和slow一次次向后移动
    4. fast和slow如果引用同一个节点,直接返回true
    5. 循环结束,没有环,返回false
     */
    private static boolean hasCircle(Node head) {
        Node fast = head; //快指针
        Node slow = head; //慢指针
        //fast在中间位置,还可以继续向后移动
        while (fast != null && fast.next != null) {
            fast = fast.next.next; //fast走两步
            slow = slow.next;      //slow走一步
            if (fast == slow) {    //fast有没有绕回来,和slow重合
                return true;       //重合就是有环
            }
        }
        return false; //fast不能再继续向后移动时,就是没有环
    }

    static class Node {
        int value;
        Node prev;
        Node next;
        Node(int value) {
            this.value = value;
        }
    }
}

翻转链表:

 翻转链表: 从头部节点开始,一个节点一个节点地拆出来,重新反向连接

代码如下,具体步骤见注释:

package list;

public class FanZhuanLianBiao {
    public static void main(String[] args) {
        Node head = new Node(1);
        head.next = new Node(2);
        head.next.next = new Node(3);
        head.next.next.next = new Node(4);
        head.next.next.next.next = new Node(5);

        Node head2 = fanZhuan(head);

        Node n = head2;
        while (n != null) {
            System.out.println(n.value);
            n = n.next;
        }
    }

    /*
    翻转链表思路: 从头部节点开始,一个节点一个节点地拆出来,重新反向连接

    1. 变量current,先引用头部节点
    2. 变量next,表示新链表中的下一个节点,开始是null
    3. 进入循环,循环条件:current!=null
    4. 定义tmp变量表示当前节点的下一个节点
    5. current的下一个,引用next
    6. 修改next变量,引用current节点
    7. 修改current变量,引用tmp节点
    8. 循环结束后,next引用的节点,就是新的头部节点,直接返回next

     */
    private static Node fanZhuan(Node head) {
        if (head == null || head.next == null) {
            return head;
        }

        Node current = head;
        Node next = null;
        while (current != null) {
            Node tmp = current.next;
            current.next = next;
            next = current;
            current = tmp;
        }
        return next;
    }

    static class Node {
        int value;
        Node prev;
        Node next;
        Node(int value) {
            this.value = value;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值