单链表中是否有环的问题

来源:互联网 发布:vb 修改批处理 编辑:程序博客网 时间:2024/05/16 11:39
   这篇是写单链表中是否有环的判断,环的长度,以及环的起始节点问题的思路以及实现。   第一个问题就是判断是否有环:   使用2个引用和一个循环可以解决这个问题,一个引用一次向后走2个节点,称为fast,一个引用一次向后走一个节点,称为slow,当fast与slow相遇时证明这个单链表有环,代码如下:
    public boolean haveCircle(){        Node fast = this.head;        Node slow = this.head;        while(fast != null){            fast = fast.next.next;            slow = slow.next;            if(fast == slow){                return true;            }        }        return false;    }
    第二个问题,环的长度,只需要记录下碰撞点的地址,从碰撞点的下一个节点遍历,再次回到这个点走过的节点数就是长度,代码如下:
public int getCircleNodeNum(){        if(this.haveCircle() == false){            return 0;        }        else{            Node fast = this.head;            Node slow = this.head;            Node p = null;            int count = 0;            while(fast != null){                fast = fast.next.next;                slow = slow.next;                if(fast == slow){                    p = fast;                    slow = slow.next;                    count+=1;                    break;                }            }            while(slow != p){                slow = slow.next;                count++;            }            return count;        }    }
    最后一个问题,寻找循环的头,也就是这个环的连接点,遇到用到这个东西:    **碰撞点到连接点的距离 = 头指针到连接点的距离**    有了这个,一个引用从头开始走,另一个从碰撞点走,2个相遇时的那个节点就是这个环的连接点,代码如下:
public Node firstCircleNode(){        //碰撞点到连接点的距离 = 头指针到连接点的距离        if(this.haveCircle() == false){            return null;        }        else{            Node fast = this.head;            Node slow = this.head;            while(fast != null){                fast = fast.next.next;                slow = slow.next;                if(fast == slow){                    break;                }            }            slow = head;            while(slow != fast){                slow = slow.next;                fast = fast.next;            }            return slow;        }    }