关于为什么要回溯时入栈,倒着输出,而不是边遍历边输出
查看原帖
关于为什么要回溯时入栈,倒着输出,而不是边遍历边输出
1161375
chenmingeng楼主2024/7/31 21:09

对比以下两种写法:

(一)

void dfs(int u) {
    path.push_back(u);
    while (!E[u].empty()) {
        auto v = E[u].back();
        E[u].pop_back();
        dfs(v);
    }
}

for (auto& u : path) printf("%d ", u);

(二)

void dfs(int u) {
    while (!E[u].empty()) {
        auto v = E[u].back();
        E[u].pop_back();
        dfs(v);
    }
    path.push_back(u);
}

reverse(path.begin(), path.end());
for (auto& u : path) printf("%d ", u);

先给 Hack 数据:

3 4
1 2
2 1
2 3
3 2

第一种的代码跑出来是 1 2 1 3 2,显然是错误的。

分析 DFS 的过程:

dfs(1): 包含边 2
    dfs(2): 包含边 1 3
        dfs(1): 没有边
        end
        dfs(3): 包含边 2
            dfs(2): 没有边
            end
        end
    end
end

问题在于「没有边」。

如果没有边,说明这个点已经遍历完毕,应该在路径的末尾输出,但 DFS 时会先进入这个点,告知程序这个点是路径末端的。但如果采用第一种代码的写法,这个点会直接计入路径并输出,这并不是我们想要的结果。

因此,路径末端的点会首先被找到,最先结束递归,并入栈,表明在结束 DFS 时入栈就是正确的。

2024/7/31 21:09
加载中...