C ++中的递归深度优先搜索(DFS)算法

时间:2015-06-26 09:09:25

标签: c++ algorithm recursion depth-first-search

我已经在类Graph中实现了图形作为邻接矩阵,其中包含访问和修改它所需的所有函数,我在DFS算法中需要的函数

// for a Graph x, node v
string x.get_node_value(v)  //returns the the label of the node
queue x.neighbors(v) //returns a queue with the adjacent nodes to the node v (nodes index on the graph starts from 1)

现在我试图实现一个递归DFS,但它总是卡在某个点上,它再也不会在它再次调用自己之后回复,所以它工作并找到目标,如果它在到达叶子节点之前存在于其路径上,但是然后它在到达叶节点后停止

通过指示颜色跟踪节点,未访问的节点为WHITE,正在进行的节点为GRAY,已完成的节点(已访问且所有子节点都已访问)为黑色。

这是启动功能:

int Search::DFSr(const std::string search_key, Graph& x, int starting_node){
    Color * visited_nodes = new Color[x.size()];
    for(int i=0; i<x.size(); i++){visited_nodes[i] = WHITE;}
    bool goal_f = 0;
    int goal = DFSUtil(search_key, x, starting_node, visited_nodes, goal_f);
    if(goal_f) return goal;
    else return -1;
}

这是访问功能:

int Search::DFSUtil(std::string search_key, Graph& x, int current_node, Color(visited_nodes)[], bool& goal_f){
    visited_nodes[current_node-1] = GREY; //-1 because array index start from 0 but nodes index on the graph starts from 1
    if(x.get_node_value(current_node) == search_key ){
        goal_f = 1;
        return current_node;
    }
    else{
        std::queue <int> childs =  x.neighbors(current_node);
        while(!childs.empty() && !goal_f){
            if(visited_nodes[childs.front()-1] == WHITE){
                return DFSUtil(search_key, x, childs.front(), visited_nodes, goal_f);
            }
            childs.pop();
        }
        visited_nodes[current_node-1] = BLACK;
    }
}

在此图表上测试:

enter image description here

只有在A,B或D范围内才能找到目标,否则它会正常退出而没有错误

1 个答案:

答案 0 :(得分:1)

The following change to your code should help:

int Search::DFSUtil(std::string search_key, Graph& x, int current_node, Color(visited_nodes)[], bool& goal_f){
    visited_nodes[current_node-1] = GREY; //-1 because array index start from 0 but nodes index on the graph starts from 1
    if(x.get_node_value(current_node) == search_key ){
        goal_f = 1;
        return current_node;
    }
    else{
        std::queue <int> childs =  x.neighbors(current_node);
        while(!childs.empty() && !goal_f){
            if(visited_nodes[childs.front()-1] == WHITE){
                int result = DFSUtil(search_key, x, childs.front(), visited_nodes, goal_f);
                if( result >= 0 ) {
                    return result;
                }
            }
            childs.pop();
        }
        visited_nodes[current_node-1] = BLACK;
    }
    return -1;
}

You can further remove goal_f variable from parameters and statements involving it. A return value is sufficient.

EDIT: the problem was in this line of code

return DFSUtil(search_key, x, childs.front(), visited_nodes, goal_f);

Here the function was returning even if the goal had not been found. So the remaining (in the queue) neighbors were not getting visited. The fix makes the function to return only if the goal has been reached. In the fix, there is also "return -1" statement in the end of the function, which indicates that the function finished without reaching the goal.

For assesment of code logic, memory, and readability, and suggestions of best practices you can post your code here: https://codereview.stackexchange.com/