算法__判斷鏈表中是否有環,並找入環對象

鏈表:是不基於物理連接的列表,是靠前對象引用後邊對象組成一串對象。(如下)

     

 鏈表中出現了環,就是我們中的最後一個引用又指回了鏈中的一個對象。(如下)

 我們就是想判斷出鏈表中是否有環,不判斷的話,我們就可能在取鏈中數據時進入死循環。

 該如何判斷這個列表中是否有環,只要我們判斷在這個鏈子是否有相同的指向。也就是兩個對象的next指的對象一樣。

 先寫個對象

public class NodeVo {

    NodeVo next;

    public NodeVo getNext() {
        return next;
    }

    public void setNext(NodeVo next) {
        this.next = next;
    }
}

 用兩個指針,在鏈表上循環。每循環一次,一個指針走兩格,一個走一格。如果有環的話最終兩個對象會相同。就好像,我們在操場跑步一樣,只要我們在繞着環行跑道跑,跑的快的一定會追上跑的慢的。這樣我們減少了,一個對象循環對比整個鏈上對象的尷尬。

 首先:我們必須知道如果鏈表中出現null,說明一定沒有環。所有判斷有環的代碼如下

public boolean glp(NodeVo nodeVo) {
   NodeVo fast = nodeVo, low = nodeVo;

   while (fast.getNext() != null && low.getNext().getNext() != null){
            fast=fast.getNext();
            low=low.getNext().getNext();

            if(fast==low)
                break;

        }

        if(fast==null||low==null)
            return false;
        
        return true;
    }

那如何找環的入口呢?(進入函數課程---啦啦啦!!!開心不?)

設low的路程爲  S,

 fast的路程則爲 2S,

 環的長度爲  R,

 鏈表開始到環口  A,

 環口到遇到的長度爲 X,

 那麼  S=A+X,

          2S=S+nR,     (n fast可能已經在環中轉了幾圈,low才進圈)

          A+X=(n-1)R+L-A;

          A=(n-1)R+L-X-A;

 所以,假設我們的n=1,首節點到入口點的長度等於相交點到入口點的距離。所以,我們找兩個對象分別從首節點和相交點開始走,每次走一格。相遇的就是相交點。


    public NodeVo getNode(NodeVo nodeVo1, NodeVo nodeVo2) {

        while (nodeVo1 != nodeVo2) {
            nodeVo1 = nodeVo1.getNext();
            nodeVo2 = nodeVo2.getNext();
        }

        return nodeVo1;

    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章