[英]Breadth-first search strategy for searching in map taking too long
使用BFS搜索的程序出現問題。 我給這個方法Node n
,如果它使用方法n.expand
找到通往目標n
方法,它應該給我返回true
。 還有其他一些類可以實現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{
}
}
}
}
考慮到close
是一個LinkedList
, close.contains
是一項非常昂貴的檢查-最壞的情況是它需要遍歷整個列表以查找該元素,所以我想這close.contains
很多時間。
如果您熟悉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.