判断单链表是否有环的算法(Java语言描述)

带环链表

这里的带环单链表可不是环形单链表,这个环可能是我们不想要的,所以需要检测。
我们就不假设有一个打结状的环了,那样跑到哪里去也不清楚,这里的“带环链表”,环必然是在末端。
这是经典问题,方法众多,但方法效率差别很大,本文试举三例,并对较优算法加以编程实现。

算法一:暴力查重

双指针即可,前一个指针在遍历单链表,后一个指针遍历前指针之前的所有结点是否有与前指针相同的结点。
如果能跑到结尾,自然是无环的,否则就跑下去,总会发现的。
这算法很暴力,不好。

算法二:HashSet查重

不需要双指针,但需要多费一些空间,建一个HashSet,里面装每一个搜索过的结点,搜到的结点如果Set里有,就是说明了有环,否则就把新搜到的结点加入HashSet里面。搜到尽头就是没环。

算法三:双指针

前一个指针一次跳两个结点,后一个结点一次跳一个结点,如果有环,则前后必能相遇。如果前者跑到尽头就说明没环。

算法核心代码(Java语言描述):

private boolean isCircular() {
    Node<T> prev = first;
    Node<T> rear = first;
    while (prev.next != null) {
        prev = prev.next;
        if (prev.next == null) {
            return false;
        }
        prev = prev.next;
        rear = rear.next;
        if (prev == rear) {
            return true;
        }
    }
    return false;
}

完整代码(Java语言描述)

public class Main {

    private static class Node<T> {
        T element;
        Node<T> next;
        Node(T element) {
            this.element = element;
        }
    }

    private static class LinkedList<T> {
        Node<T> first;
        private boolean isCircular() {
            Node<T> prev = first;
            Node<T> rear = first;
            while (prev.next != null) {
                prev = prev.next;
                if (prev.next == null) {
                    return false;
                }
                prev = prev.next;
                rear = rear.next;
                if (prev == rear) {
                    return true;
                }
            }
            return false;
        }
    }

    public static void main(String[] args) {
        Node<Integer> node1 = new Node<>(1);
        Node<Integer> node2 = new Node<>(2);
        Node<Integer> node3 = new Node<>(3);
        Node<Integer> node4 = new Node<>(4);
        Node<Integer> node5 = new Node<>(5);
        Node<Integer> node6 = new Node<>(6);
        Node<Integer> node7 = new Node<>(7);
        Node<Integer> node8 = new Node<>(8);
        Node<Integer> node9 = new Node<>(9);
        node1.next = node2;
        node2.next = node3;
        node3.next = node4;
        node4.next = node5;
        node5.next = node6;
        node6.next = node7;
        node7.next = node8;
        node8.next = node9;
        node9.next = node4;
        LinkedList<Integer> list = new LinkedList<>();
        list.first = node1;
        System.out.println("链表是否有环:" + list.isCircular());
    }

}
发布了538 篇原创文章 · 获赞 1098 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/weixin_43896318/article/details/104383604