链表、单向双向循环链表、遍历、快慢指针(从入门到入坑)

链表、单向双向循环链表、遍历、快慢指针(从入门到入坑)

什么是链表

链表是一种基本数据结构,取值虽然没有数组方便,但是在扩容、删除时,比数组方便很多。链表的基本单位是一个个节点,节点内存储数据的同时还能存储下一个节点的地址,所以在删除、新建节点的时候,比数组高效很多。

链表的分类

单向链表:
如果最后一个节点的下一个节点指向是null,就是一个单向链表
如果最后一个节点的下一个节点指向头结点,就是一个单向循环列表
单向链表
单向循环链表

//单向链表的节点
public class Link {
    int value; //可以存储数据
    Link next; //下一个节点的地址
    
    public Link() {}
    public Link(int value) { this.value = value; }
}

link1 = new Link();
link2 = new Link();
link3 = new Link();
//单向链表
link1.next = link2;
link2.next = link3;
link3.next = null;
//单向循环列表
link1.next = link2;
link2.next = link3;
link3.next = link1

双向链表:
如果两个相邻的节点之间是有相互的指向,且最后一个节点的下一个个节点指向null,就是一个双向链表
如果两个相邻的节点之间是有相互的指向,且最后一个节点的下一个节点指向头结点,就是一个双向循环列表
双向链表
双向循环链表

//双向链表的节点
public class Link {
    int value; //可以存储数据
    Link next; //下一个节点的地址
    Link last; //上一个节点的地址
    
    public Link() {}
    public Link(int value) { this.value = value; }
}

link1 = new Link();
link2 = new Link();
link3 = new Link();
//双向链表
link1.next = link2;
link1.last = null;
link2.next = link3;
link2.last = link1;
link3.next = null;
link3.last = link2;
//双向循环列表
link1.next = link2;
link1.last = link3;
link2.next = link3;
link2.last = link1;
link3.next = link1
link3.last = link2;

链表的遍历

双向链表和单向链表遍历方法相同,并且双向链表因为有上一项的地址,所以实际操作使用起来更方便。

    public static void main(String[] args) {
        Link link1 = new Link();
        Link link2 = new Link();
        Link link3 = new Link();
        link1.next = link2;
        link2.next = link3;
        link3.next = link1;


        Link index = link1;
        while (true){
            System.out.print(index.value+" "); //输出值
            //判断是否为最后一个
            if (index.next == null){
                // 链表已经到达最后一位
                System.out.println("非循环链表");
                break;
            }
            index = index.next;
            //判断是否是循环列表
            if (index == link1){
                System.out.println("循环链表");
                break;
            }
        }
    }
    //这段代码会输出: 0 0 0 循环链表

快慢指针

快慢指针是定义两个指针(在java里没有指针的概念,应该是引用),快的指针一次前进两个节点,慢的指针每次前进一个节点,因为快指针是慢指针速度的两倍,所以快指针到达最后节点的时候,慢指针刚好到达链表中间节点(需要注意节点个数的奇偶)。利用快慢指针还可以判断链表是否为循环链表。
以上面的单向链表结构为例判断链表是否为循环链表:

 public static void main(String[] args) {
        Link link1 = new Link();
        Link link2 = new Link();
        Link link3 = new Link();
        link1.next = link2;
        link2.next = link3;
        link3.next = link1;

		//定义快慢指针
        Link fast = link1;
        Link slow = link1;
        while (true){
            if (fast.next==null || fast.next.next==null){
                /*
                    只要有null就不是循环链表
                    当链表节点个数为奇数,就是(fast.next = null),慢指针正好是中间节点
                    当链表节点数为偶数,(fast.next = null)且(fast.next.next=null)慢指针是中间的两个节点的前一个
                */
                System.out.println("非循环链表");
                break;
            }
            fast = fast.next.next;
            slow = slow.next;
            if (fast.equals(slow)){
                //当快慢指针重合,就说明这是一个环形链表
                System.out.println("循环链表");
                break;
            }
        }
    }

快慢指针在算法题里面用到的非常多,实际开发中合理使用会大大增加代码的执行效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值