簡體   English   中英

為什么我在 DFS 中有 StackOverflow?

[英]Why I have StackOverflow in DFS?

我正在嘗試在c++中實現 DFS 算法。 我用它來回答這個問題:“兩個頂點是否連接?”,但是出了點問題。

有時程序給出正確答案,有時會因0xC00000FD代碼而崩潰。 我用谷歌搜索了一下,現在知道了,這是StackOverflow錯誤。

這是代碼:

const int N = 4;                     // The minimal example I've know is a graph with 4 vertexes.
std::vector<int> graph[N];           // Our graph
int start = 0;                       // The start vertex
int finish = N - 1;                  // The finish vertex

bool dfs(int old, int v) {           // The DFS function
    if (v == finish)
        return true;
    bool ans = false;
    for (int u : graph[v]) {
        if (u != old)
            ans |= dfs(v, u);
    }
    return ans;
}

void init_graph_ok() {               // With this graph all works fine
    graph[0] = { 1 };               
    graph[1] = { 2 };                // 0 (st) -- 1 -- 2 -- 3 (fin)
    graph[2] = { 3 };
    graph[3] = {};
}
void init_graph_bad() {              // With this graph I have StackOverflow
    graph[0] = { 1, 2 };
    graph[1] = { 2, 0 };             // 0 (st) -- 1 -- 2 -- 3 (fin)
    graph[2] = { 0, 3 };             // ^--------------^
    graph[3] = {};
}

int main() {
    init_graph_bad();
//  init_graph_ok();
    std::cout << dfs(-1, 0);
}

這是因為您的代碼不止一次地訪問特定節點,因此您的代碼會陷入無限遞歸。

由於無限遞歸調用,堆棧 memory 被完全填滿,最終導致堆棧溢出錯誤。

解決方案:通過使用visited數組,允許每個節點幾乎被訪問一次,如下所示:

const int N = 4;                     // The minimal example I've know is a graph with 4 vertexes.
std::vector<int> graph[N];           // Our graph
int start = 0;                       // The start vertex
int finish = N - 1;                  // The finish vertex

bool visited[N+1];

bool dfs(int old, int v) {           // The DFS function

    if(visited[v]){
        return true;
    }
    visited[v] = true;
    
    if (v == finish)
        return true;
        
    bool ans = false;
    
    for (int u : graph[v]) {
        if (u != old)
            ans |= dfs(v, u);
    }
    
    return ans;
}

void init_graph_ok() {               // With this graph all works fine
    graph[0] = { 1 };               
    graph[1] = { 2 };                // 0 (st) -- 1 -- 2 -- 3 (fin)
    graph[2] = { 3 };
    graph[3] = {};
}
void init_graph_bad() {              // With this graph I have StackOverflow
    graph[0] = { 1, 2 };
    graph[1] = { 2, 0 };             // 0 (st) -- 1 -- 2 -- 3 (fin)
    graph[2] = { 0, 3 };             // ^--------------^
    graph[3] = {};
    memset(visited, false, N+1);
}

int main() {
    init_graph_bad();
//  init_graph_ok();
    std::cout << dfs(-1, 0);
} 

PS:不要擔心循環,因為這個邏輯也會處理循環。

暫無
暫無

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

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