我的程序使用BFS搜索时遇到问题。我正在使用此方法Node n
如果它使用方法true
找到了通往目标n
的路,则应该返回n.expand
。还有一些其他类为Node
和expand
实现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{
}
}
}
}
答案 0 :(得分:1)
close.contains
是close
, LinkedList
是一个非常昂贵的检查 - 在最坏的情况下,它需要遍历整个列表中寻找元素,所以我的猜测是那里有很多运行时间。
如果你熟悉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)。