单链表是否有环,环的长度,以及环的起始点

寻找倒数第k个结点

public void  lastk(int k){
        Entry cur1=head;
        Entry cur2=head;
        if(k<0||k>getlength()){
            System.out.println("超出链表范围");
        }
        while(k-1>0){//当k合法的时候,让cur1先往后移动,比如要寻找倒数第二个结点,则让cur1先往后移动俩次
            cur1=cur1.next;
            k--;
        }
        while(cur1.next!=null){//cur1先移动之后,让cur1与cur2同时移动
            cur1=cur1.next;
            cur2=cur2.next;
            if(cur1.next==null){//当cur1移动到最后一个结点时,cur2此时就是我们需要找出的结点
                System.out.println(cur2.data);
            }
        }

    }

代码原理:
让cur1先往后移动,比如要寻找倒数第二个结点,则让cur1先往后移动俩次,然后cur1 cur2同时向后移动,直到cur1移动到最后一个结点,此时,cur2就移动到了我们需要找的结点。

判断一个链表是否有环:

public boolean isloop(){//判断是否有环
    Entry fast=head;
    Entry slow=head;

    while(fast!=null&&fast.next!=null)
    {
        fast=fast.next.next;
        slow=slow.next;
        if(fast==slow){
            return true;
        }
    }
    return false;



}

设置两个指针(fast, slow),初始值都指向头结点,slow每次前进一步,fast每次前进二步,如果链表存在环,则fast必定先进入环,而slow后进入环,两个指针必定相遇。

计算环的长度:




public void getLoopLength(){
    Entry fast = head;
    Entry slow = head;


    while(fast != null && fast.next != null){
        fast = fast.next.next;
        slow = slow.next;

        //输出环长
        while(fast == slow) {

            int len = 0;
            fast = fast.next.next;
            slow = slow.next;
            while (fast != slow) {
                len++;
                fast = fast.next.next;
                slow = slow.next;



            }System.out.println("环长度为:"+len);
        }
        }
    }

从第一次相遇点也就是环的起始位置开始,快慢指针同时继续移动,直到下次二者相遇,慢指针走过的长度就是环的长度

寻找环的起点

public void begin()
{
    Entry fast=head;
    Entry slow=head;
while(fast!=null&&fast.next!=null)
{
fast=fast.next.next;
slow=slow.next;
if(fast==slow){
    break;}

}
Entry a=head;
while (a != slow) {
    a = a.next;//让a从头结点开始,slow从相遇点开始,当俩者再次相遇的结点就是环的起始结点
    slow = slow.next;

}
System.out.println(slow.data);


}

如图所示这里写图片描述
从表头到入口点的距离,等于从相遇点到入口点的距离。

判断俩个单链表是否相交

public static void   cteatcut(TestLink t1,TestLink t2){//先创建俩个有交点的单链表
        TestLink.Entry head1=t1.getHead();
        TestLink.Entry head2=t2.getHead();
        head1.next.next=head2.next.next;
            }
    public static boolean iscut(TestLink t1,TestLink t2){
        TestLink.Entry head1=t1.getHead();
        TestLink.Entry head2=t2.getHead();

        int len1=t1.getlength();
        int len2=t2.getlength();
        int my_len=len1-len2;
        if(my_len<0){//为了保证len1代表的是比较长的单链表
            len1=t2.getlength();
            len2=t1.getlength();
                    }
        for(int i=0;i<my_len;i++){//让长的单链表先向后移动my—len个结点,此时,俩个链表才相当于在同个起跑线上
            head1=head1.next;
        }
        while(head1!=null&&head2!=null&&head1!=head2){//遍历俩个单链表,如果有一样的结点,则说明俩个单链表有交点
            head1=head1.next;
            head2=head2.next;
        }
        if(head1==head2&&head1!=null){
            return true;
        }else{
            return false;
        }

    }

单链表的逆置

    public  void nizhi1(){//逆顺打印
        Entry newhead=null;
        Entry prev=null;
        Entry cur=head;
        while(cur!=null){
            Entry curnest=cur.next;
            if(curnest==null){
                newhead=cur;
            }
            cur.next=prev;
            prev=cur;
            cur=curnest;
        }
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值