反向排序图表的遍历

时间:2015-07-01 15:29:30

标签: c++ stl graph-theory

这个问题是我从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;
}

这是我正在考虑的图表:

enter image description here

图表中的输出为:1->2->4->5->3 但我得到的输出是:1->3->2->5->4

我可以观察到它也是一个有效的DFS遍历但是从右到左oredr为什么会这样呢?如果我的代码中的哪一部分出错我错了?如果需要进行DFS遍历,那么单个图形的多次遍历不会产生不正确的结果吗?

3 个答案:

答案 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)