为什么我需要在广度优先搜索中使用访问状态?

时间:2014-10-19 13:33:09

标签: algorithm

我已经实现了广度优先搜索算法(实际上,它是广泛的首次遍历,因为我不是在搜索任何特定节点,只是按访问顺序打印出节点值)并且没有使用任何状态跟踪每个节点 - 即我没有将任何节点标记为已访问。在大多数BFS实现中,我看到了将节点标记为已访问的概念,因此您永远不会访问它两次,但在我的实现中,我无法看到任何可能的情况。

有人可以解释为什么访问状态是有用和/或必要的吗?

这是我的实施:

import java.util.LinkedList;
import java.util.Queue;

public class BFS {

    public static void printTree(Node root) {
        Queue<Node> queue = new LinkedList<Node>();
        queue.add(root);
        while(queue.isEmpty() == false) {
            Node curr = queue.remove();
            System.out.println(curr.getValue());
            if (curr.getLeft() != null) {
                queue.add(curr.getLeft());
            }
            if (curr.getRight() != null) {
                queue.add(curr.getRight());
            }
        }
    }

    public static void main(String[] args) {
        Node leaf1 = new Node(5);
        Node leaf2 = new Node(6);
        Node leaf3 = new Node(7);
        Node leaf4 = new Node(7);
        Node leaf5 = new Node(11);
        Node rightRightRoot = new Node(12, leaf4, leaf5);
        Node leftRoot = new Node(1, leaf1, leaf2);
        Node rightRoot = new Node(9, leaf3, rightRightRoot);

        Node root = new Node(4, leftRoot, rightRoot);
        printTree(root);
    }

    static class Node {
        private int value;
        private Node left, right;

        public Node(int value, Node left, Node right) {
            this.value = value;
            this.left = left;
            this.right = right;
        }

        public Node(int value) {
            this.value = value;
        }

        public int getValue() {
            return value;
        }

        public Node getLeft() {
            return left;
        }

        public Node getRight() {
            return right;
        }
    }
}

2 个答案:

答案 0 :(得分:3)

你见过的大多数BFS实现都会遍历任意图形,然后穿过树。这两种情况的区别在于周期。任意图可以有它们,并且状态对于不将节点放入队列两次是必要的,但在你的情况下你可能没有它们。

答案 1 :(得分:0)

您的代码引用了一棵树。根据定义,树不能有循环,因此如果您正在遍历树,则不需要跟踪是否已访问过顶点。图形可以具有循环,因此它使多个顶点成为顶点的合法父项。

例如,使用四个顶点(A,B,C,D)和以下拓扑图:

 A
/ \
B C
\ /
 D

如果从A开始广度优先搜索,则B&amp; C可以达到D.执行期间,B&amp; C会将D添加到队列中,因此它将被访问并打印两次。

以下代码将打印4次:

Node D = new Node(4);
Node C = new Node(3, D, null);
Node B = new Node(2, null, D);
Node A = new Node(1, B, C);
printTree(A);