簡體   English   中英

使用迭代深度優先搜索算法的未加權圖的最短路徑

[英]Shortest path for unweighted graph using iterative depth first search algorithm

我已經設法使用遞歸 dfs 找到了未加權圖的最短路徑。 這是這樣的嘗試。

void dfsHelper(graph*& g, int start,int end, bool*& visited, int& min, int i) {
    visited[start] = true;
    i = i + 1;
    if (start == end) {
        if (i<=min) { min = i; }
    }
    node* current = g->adj[start];
    while (current != NULL) {
        if (!visited[current->dest]) {
            dfsHelper(g, current->dest,end, visited,min,i);
        }
        current = current->next;
    }
    visited[start] = false;
}

但是,對於像這樣的 dfs 迭代算法,我應該如何處理。

void dfsItr(graph*& g, int start, int end) {
    bool* isVisited = new bool[g->numVertex];
    for (int i = 0; i < g->numVertex; ++i) {
        isVisited[i] = false;
    }
    stack<int> st;
    isVisited[start] = true;
    st.push(start);

    while (!st.empty()) {
        start = st.top();
        cout << start << " ";
        st.pop();
        node* current = g->adj[start];
        while (current != NULL) {
            if (!isVisited[current->dest]) {
                isVisited[current->dest] = true;
                st.push(current->dest);
                if (current->dest == end) {
                    cout << current->dest << endl; 
                }
            }
            current = current->next;
        }

    }
}

是否有任何算法詳細說明要遵循的程序。 我很清楚使用此處給出或 此處建議的 BFS 算法找到最短路徑。 關於為什么這樣的想法適用於 BFS,我最初的直覺是遍歷逐層發生,多個子節點在每一層共享相同的父節點,因此只需跟隨父節點就很容易回溯。 在迭代 dfs 中,情況並非如此。 有人可以說明如何進行。 是否有任何經過驗證的算法可以解決這種情況。 謝謝。

我不完全清楚你在問什么......

如果您詢問如何優化 DFS 的迭代實現,我在這里要做的一件事不是使用stack而是編寫自己的具有 LIFO 接口但預分配內存的集合。
其他優化空間是不使用流運算符,因為它們比printf慢得多。 查看這個關於性能的答案部分。 另外,一直打印到STDOUT真的有意義嗎? 如果性能是關鍵,這可能每幾次迭代就完成一次,因為 IO 操作真的很慢。

如果你問什么算法比 DFS 方法更好,很難回答,因為它總是取決於給定的問題。 如果您想找到節點之間的最佳路徑,請選擇基於 BFS 的(例如Dijkstra 算法),因為與 DFS 相比,它在未加權圖中的表現最佳(順便說一句。A* 在這里不起作用,因為沒有權重和沒有花哨的啟發式,它只會崩潰到 DFS)。 如果您對這個主題更感興趣,您可以在系列叢書中找到更多關於可以采取哪些技巧來優化尋路的信息。

最后但並非最不重要的一點是,也嘗試一些啟發式方法 也許沒有必要進行詳盡的搜索來找到問題的解決方案。

這是一個例子,說明了為什么深度優先搜索,即使有一些優化,也可能是一個壞主意。 (這幾乎總是一個壞主意,但插圖並沒有那么遠)。

假設您的圖是節點 0, ..., n 上的完整圖,即包含所有可能邊的圖。 進一步假設邊總是按順序出現在數據結構中,並且您想找到從 0 到 n 的最短路徑。

朴素的深度優先搜索將探索 (n-1)! 路徑,然后才能找到最佳路徑。 廣度優先搜索探索 n 條路徑。 這兩種情況本質上都是它們各自算法的最壞情況(編輯:該圖的最壞情況排序)。

您可以通過以下幾種方式優化深度優先搜索:

1) 如果當前路徑比目前最佳成功路徑短一跳,並且不是成功路徑,則修剪搜索。

2)更激進,每次第一次訪問一個節點時,將當前路徑的長度存儲在該節點中。 以后每次訪問時,將當前路徑的長度與之前存儲的長度進行比較。 如果新路徑較短,則存儲新長度。 否則,修剪搜索。

在這兩者中,(2) 是更積極的優化。 它比廣度優先搜索更糟糕。 在廣度優先搜索中,每次你通過一個節點都是因為你通過最短路徑到達它,並且在這一點上該節點成為所有進一步路徑遍歷的死胡同。 這些都不是深度優先搜索的情況。 此外,存儲長度的(漸近)內存成本並不比使用廣度優先隊列好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM