用于在地图中搜索的广度优先搜索策略花费太长时间

时间:2014-04-11 08:43:48

标签: java algorithm search graph map

我的程序使用BFS搜索时遇到问题。我正在使用此方法Node n如果它使用方法true找到了通往目标n的路,则应该返回n.expand。还有一些其他类为Nodeexpand实现isTarget和方法。当它距离很近时,它可以工作,但是当这些节点之间的距离较长时,它需要大约15分钟或更长时间。任何人都可以帮我解决这个问题吗?

public boolean prog(Node n)
{
    Queue<Node> FIFO = new LinkedList<Node>();
    List<Node> close = new LinkedList<Node>();

    FIFO.add(n);
    while (true) {
        n = FIFO.poll();

        if (close.contains(n)) {
        } else {
            close.add(n);
        }
        close.add(n);
        for (int i = 0; i < n.expand().size(); i++) {
            if (!close.contains(n.expand().get(i))) {
                FIFO.add(n.expand().get(i));
            } else {
            }

            if (n.expand().get(i).isTarget()) {
                return true;
            }else{
            }
        }
    }
}

3 个答案:

答案 0 :(得分:1)

考虑到close.containsclose

LinkedList是一个非常昂贵的检查 - 在最坏的情况下,它需要遍历整个列表中寻找元素,所以我的猜测是那里有很多运行时间。

我建议您尝试使用HashSetTreeSet

如果你熟悉big-O符号(如果没有,我建议你阅读this post),LinkedList.contains是O(n),HashSet.contains是预期的O( 1)和TreeSet.contains是O(log n)。


我还建议您将n.expand()调用移出for循环,而不是将其存储在您使用的临时变量中。每次调用n.expand()(可能)都会导致必须再次设置相邻节点的集合。


The A* search algorithm也可能是BFS的替代品。这涉及到达目的地的估计成本(称为启发式&#39;),使我们能够专注于我们认为接近目的地的节点。

答案 1 :(得分:0)

你可以想到双向BFS

将源和目标都视为源并检查它们是否在某个中间节点中相遇。这应该可以节省很多时间。

答案 2 :(得分:0)

你的代码看起来很奇怪,我修了一下。

public boolean prog(Node n)
{
    Queue<Node> FIFO = new LinkedList<Node>();
    List<Node> close = new LinkedList<Node>();

    FIFO.add(n);
    while (!FIFO.empty()) {
        n = FIFO.poll();
        if( n.isTarget() )
            return true;         
        for (int i = 0; i < n.expand().size(); i++) {
            Node nxt = n.expand().get(i); // Note dukeling suggestion here, I don't know what's behind expand()
            if (!close.contains(nxt)) {
                FIFO.add(nxt); close.add(nxt);
            }
        }
    }
    return false;
}

由于使用了close.contains(),它的复杂度也很差(O(NM)而不是O(N + M),其中N - 节点数,M - 边数)。

你应该添加内部bool标志&#34;使用&#34;到节点(然后得到(i)将提供有关该节点的必要信息。)

如果不可能,您应该将identifyicator(int)添加到每个节点,这样您就可以在本地bool数组中标记它(使用[id])。但是如果Nodes计数对于本地数组来说太大了(最多10 ^ 6),我认为你根本不会使用bfs。

UPD Dukeling提到的HashSet可能在中间情况下提供O(N + M),在最差情况下提供O(NM)。 TreeSet可以提供稳定的O(MlogN)。