簡體   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