如何用JAVA程式來查詢連結列表是否包含迴圈

jdon發表於2019-01-26


查詢連結串列是否包含迴圈的演算法

迭代連結串列時使用快速和慢速兩個指標。快速指標在每次迭代中移動兩個節點,而慢速指標移動到一個節點。如果連結串列包含迴圈或迴圈,那麼在迭代過程中,快指標和慢指標都會在某個點上相遇。如果它們不相交,並且快速或慢速將指向空,那麼連結串列就不是迴圈的,它不包含任何迴圈。這是精確的演算法

1)使用快速和慢速兩個指標
2)每次迭代快速移動兩個節點,慢速移動一個節點
3)如果快速和慢速相遇,則連結串列包含迴圈
4)如果fast指向空或fast.next指向空,則連結串列不是迴圈的。

下一部分包含Java程式來檢查連結串列是否包含迴圈,這是上述演算法的精確實現。該演算法也被稱為Floyd的迴圈查詢演算法,通常被稱為Tortoise and Hare演算法,用於查詢連結串列中的迴圈。

Java程式檢查連結串列是否為迴圈

這個Java程式使用LinkedList(不Java.UTI.LIKEDLIST)和連結串列的前一個節點類,修改了新增ToStTrn()方法和AppEntoTead()方法。另外,連結串列的iscyclic()方法用於實現邏輯,以確定連結串列是否包含迴圈。隨後is cyclic()如果連結串列是迴圈的,則返回true,否則返回false。

/*
 * Java class to represent linked list data structure.
 */
public class LinkedList {
    private Node head;
    public LinkedList() { this.head = new Node("head"); }   
    public Node head() { return head;}
   
    public void appendIntoTail(Node node) {
        Node current = head;
       
        //find last element of LinkedList i.e. tail
        while(current.next() != null){
            current = current.next();
        }
        //appending new node to tail in LinkedList
        current.setNext(node);
    }
   
    /*
     * If singly LinkedList contains Cycle then following would be true
     * 1) slow and fast will point to same node i.e. they meet
     * On the other hand if fast will point to null or next node of
     * fast will point to null then LinkedList does not contains cycle.
     */
    public boolean isCyclic(){
        Node fast = head;
        Node slow = head;
       
        while(fast!= null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
           
            //if fast and slow pointers are meeting then LinkedList is cyclic
            if(fast == slow ){
                return true;
            }
        }
        return false;
    }
   
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        Node current = head.next();
        while(current != null){
           sb.append(current).append("-->");
           current = current.next();
        }
        sb.delete(sb.length() - 3, sb.length()); // to remove --> from last node
       return sb.toString();
    }

    public static class Node {
        private Node next;
        private String data;

        public Node(String data) {
            this.data = data;
        }

        public String data() { return data; }
        public void setData(String data) { this.data = data;}

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

        @Override
        public String toString() {
            return this.data;
        }
    }
}


測試迴圈的連結串列

在本節中,我們將使用帶有兩個連結串列的Java main方法測試,一個包含迴圈而另一個不迴圈。 您甚至可以為isCyclic()方法編寫JUnit測試用例,以測試不同位置的迴圈的不同連結串列。 這是連結串列不包含任何迴圈的第一個測試。

/**
 *
 * Java program to find if LinkedList contains loop or cycle or not.
 * This example uses two pointer approach to detect cycle in linked list.
 * Fast pointer moves two node at a time while slow pointer moves one node.
 * If linked list contains any cycle or loop then both pointer will meet some time.
 *
 * @author Javin Paul
 */
public class LinkedListTest {

    public static void main(String args[]) {

        //creating LinkedList with 5 elements including head
        LinkedList linkedList = new LinkedList();
        linkedList.appendIntoTail(new LinkedList.Node("101"));
        linkedList.appendIntoTail(new LinkedList.Node("201"));
        linkedList.appendIntoTail(new LinkedList.Node("301"));
        linkedList.appendIntoTail(new LinkedList.Node("401"));

        System.out.println("Linked List : " + linkedList);

        if(linkedList.isCyclic()){
            System.out.println("Linked List is cyclic as it contains cycles or loop");
        }else{
            System.out.println("LinkedList is not cyclic, no loop or cycle found");
        }    

    } 
   
}

Output:
Linked List : 101-->201-->301-->401
LinkedList is not cyclic, no loop or cycle found


現在讓我們改變連結串列,使其包含迴圈

//creating LinkedList with 5 elements including head
LinkedList linkedList = new LinkedList();
linkedList.appendIntoTail(new LinkedList.Node("101"));
LinkedList.Node cycle = new LinkedList.Node("201");
linkedList.appendIntoTail(cycle);
linkedList.appendIntoTail(new LinkedList.Node("301"));
linkedList.appendIntoTail(new LinkedList.Node("401"));
linkedList.appendIntoTail(cycle);

//don't call toString method in case of cyclic linked list, it will throw OutOfMemoryError
//System.out.println("Linked List : " + linkedList);

if(linkedList.isCyclic()){
   System.out.println("Linked List is cyclic as it contains cycles or loop");
}else{
   System.out.println("LinkedList is not cyclic, no loop or cycle found");
}    

Output:
Linked List is cyclic as it contains cycles or loop


 

相關文章