繁体   English   中英

在地图上进行搜索花费的时间太长的广度优先搜索策略

[英]Breadth-first search strategy for searching in map taking too long

使用BFS搜索的程序出现问题。 我给这个方法Node n ,如果它使用方法n.expand找到通往目标n方法,它应该给我返回true 还有其他一些类可以实现NodeexpandisTarget方法。 如果距离较短,则可以使用,但是如果这些节点之间的距离较长,则大约需要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{
            }
        }
    }
}

考虑到close是一个LinkedListclose.contains是一项非常昂贵的检查-最坏的情况是它需要遍历整个列表以查找该元素,所以我想这close.contains很多时间。

我建议您改用HashSetTreeSet

如果您熟悉big-O表示法(如果不是,我建议您阅读这篇文章 ), LinkedList.contains为O(n), HashSet.contains为O(1), TreeSet.contains为O(log n) 。


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


A *搜索算法也可以作为替代BFS的考虑因素。 这涉及估算到目的地的成本(称为“启发式”),使我们能够专注于我们认为与目的地接近的节点。

您可以想到双向BFS

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

您的代码看起来很奇怪,我已对其进行了一些修复。

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-边缘数)。

您应该在Node上添加内部bool标志“ used”(然后get(i)将提供有关此信息的必需信息)。

如果不可能,则应在每个节点上添加标识符(int),以便可以在本地布尔数组(used [id])中将其标记为已访问。 但是,如果节点数对于本地数组而言太大(最多10 ^ 6),那么我认为根本就不会使用bfs。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM