判断单链表是否有环,若有环输出环的入口节点

思路:

1、快慢引用 fast 一次跑两个,slow一次跑一个两者相遇有环,但相遇点不一定是入口点,如何证明是不是入口点?  快路径长度=2慢路径长度

2、代码实现

public class Link<T extends Comparable<T>> {
    private Entry<T> headEntry;
    private Entry<T> tailEntry;//标记尾部

    public Entry<T> getEntry(T value){
        for(Entry<T> p = headEntry;p!=null;p=p.getNext()){
            if(p.getValue().compareTo(value) ==0){
                return p;
            }
        }
        return null;
    }

    public void addHead(T value){
        Entry<T> p=new Entry<>(value);
        //空链表
        if(headEntry==null){
            headEntry=p;
            tailEntry=p; //标记尾巴
        }else {
            p.setNext(headEntry);
            headEntry=p;//新链表起始位置
        }
    }

    public void addTail(T value){
        Entry<T> newEntry=new Entry<>(value);
        if(headEntry ==null){
            headEntry= newEntry;
            tailEntry= newEntry;
        }else {
            tailEntry.setNext(newEntry);
            tailEntry=newEntry;
        }
    }

    public void removeHead(){
        if(headEntry==null){
            return;
        }
        headEntry.setValue(null);
        headEntry=headEntry.getNext();
        if(headEntry==null){
            tailEntry=null;
        }
    }

    public void removeTail(){
        if (headEntry==null){
            return;
        }
        if(headEntry.getNext()==null){
            headEntry=null;
            tailEntry=null;
            return;
        }
        tailEntry.setValue(null);//防止内存泄漏
        //为尾巴找前驱
        Entry<T> beforeTail=headEntry;
        for(;beforeTail.getNext().getNext()!=null;beforeTail=beforeTail.getNext()){
            ;
        }
        //找到尾巴前驱
        tailEntry=beforeTail;
        tailEntry.setNext(null);//新尾部结点next=null
        beforeTail.setNext(null);
    }
    public void removeValue(T value){
        if(headEntry==null){
            return;
        }
        if(headEntry.getValue().compareTo(value)==0){
            headEntry.setValue(null);//防止内存泄漏
            headEntry=headEntry.getNext();
            if(tailEntry==headEntry){
                tailEntry=null;
            }
            return;
        }
        //p保存要删结点的前驱结点
        for(Entry<T>p=headEntry;p.getNext()!=null;p=p.getNext()){
            if(p.getNext().getValue().compareTo(value)==0){
                p.getNext().setValue(null);//防止内存泄漏
                p.setNext(p.getNext().getNext());
                tailEntry=p;//此时更新新尾部
                break;
            }
        }
    }
    public void show(){
        for(Entry p=headEntry;p!=null;p=p.getNext()){
            System.out.println(p.getValue()+" ");
        }
        System.out.println();
    }

    private int getLength(){
        int count =0;
        for(Entry<T> p=headEntry;p!=null;p=p.getNext()){
            count++;
        }
        return count;
    }
    public Entry<T> isCircle(){
        Entry<T> fast =headEntry;
        Entry<T> slow =headEntry;
        do{
            if(fast==null||fast.getNext()==null){
                return null;
            }
            slow=slow.getNext();
            fast=fast.getNext().getNext();
        }while (fast!=slow);
        return slow;
    }
    //输出环的入口结点:当前链表环的入口结点
    public Entry<T> getCircleMeetEntry(){
        Entry<T> meet=isCircle();
        if(meet ==null){
            return null;
        }
        Entry<T> p=headEntry;
        Entry<T> q=meet;
        while (p!=q){
            p=p.getNext();
            q=q.getNext();
        }
        return p;
    }

}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值