这个问题是我从DFS图遍历算法中得到的奇怪行为的结果。我试图实现DFS,这是我的代码:
#include<iostream>
#include<stack>
#include<vector>
#include<map>
using namespace std;
map<int,bool> discovered;
map< int , vector<int> > graph {
{1,{2,3}},
{2,{1,4,5}},
{3,{1}},
{4,{2}},
{5,{2}}
};
vector <int> visited;
void clear_graph(){
for( map<int,bool>:: iterator iter = discovered.begin(); iter != discovered.end(); iter++)
discovered[iter->first] = false;
}
void dfs( int start ) {
int current;
int next;
unsigned int i;
stack <int> vertices;
discovered[start] = true;
vertices.push(start);
while (!vertices.empty()){
current = vertices.top();
visited.push_back(current);
vertices.pop();
for( i = 0 ; i<graph[current].size() ; i++){
next = graph[current][i];
if ( !discovered[next] ){
discovered[next] = true;
vertices.push(next);
}
}
}
}
int main() {
clear_graph();
int start = 1;
dfs(start);
vector<int> ::iterator vi;
for( vi=visited.begin(); vi!=visited.end();vi++)
cout<<*vi<<" ";
return 0;
}
这是我正在考虑的图表:
图表中的输出为:1->2->4->5->3
但我得到的输出是:1->3->2->5->4
我可以观察到它也是一个有效的DFS遍历但是从右到左oredr为什么会这样呢?如果我的代码中的哪一部分出错我错了?如果需要进行DFS遍历,那么单个图形的多次遍历不会产生不正确的结果吗?
答案 0 :(得分:2)
这只是算法上的差异问题。
如果以递归方式执行,则在备份到3之前完全迭代2,因此1->2->4->5->3
。如果你迭代地执行它,你会以相反的顺序访问邻居,所以你最终会先完全迭代3,因此1->3->2->5->4
。您的算法仍然是正确的深度优先搜索算法,与图像恰好使用的算法不同。
如果你想保留你的迭代解决方案但得到与递归解决方案相同的结果,你可以改变你的顺序。变化:
next = graph[current][i];
为:
next = graph[current][graph[current].size() - i - 1];
答案 1 :(得分:1)
您的遍历是相反的,因为您使用堆栈数据结构,它以相反的顺序(后进先出)弹出项目,将它们推入堆栈。您将顶点向前推入堆栈,因此您可以从堆栈中向后移动它们。
以下内容评论解释了为什么会发生逆转:
void dfs( int start ) {
int current;
int next;
unsigned int i;
stack <int> vertices;
discovered[start] = true;
vertices.push(start);
while (!vertices.empty()){
// here you pop vertices from the stack in the reverse order of how
// the vertices were pushed into the stack
current = vertices.top();
visited.push_back(current);
vertices.pop();
// here you traverse the vertices forward
for( i = 0 ; i<graph[current].size() ; i++){
next = graph[current][i];
if ( !discovered[next] ){
discovered[next] = true;
// here you push vertices into the stack
vertices.push(next);
}
}
}
}
答案 2 :(得分:1)
您正按照从左到右的顺序将子节点推入堆栈。因此,将首先弹出并处理右侧节点。要按从左到右的顺序遍历子项,请将for循环更改为:
for (int i = graph[current].size()-1; i >= 0; --i)