[英]c++ directed graph depth first search
我正在尝试为有向图编写方法DFS方法。 现在,我遇到了细分错误,我真的不确定它在哪里。 从我对有向图的理解中,我相信我的逻辑是正确的……但是换个新的眼睛会很有帮助。
这是我的功能:
void wdigraph::depth_first (int v) const {
static int fVertex = -1;
static bool* visited = NULL;
if( fVertex == -1 ) {
fVertex = v;
visited = new bool[size];
for( int x = 0; x < size; x++ ) {
visited[x] = false;
}
}
cout << label[v];
visited[v] = true;
for (int v = 0; v < adj_matrix.size(); v++) {
for( int x = 0; x < adj_matrix.size(); x++) {
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
cout << " -> ";
depth_first(x);
}
if ( v == fVertex ) {
fVertex = -1;
delete [] visited;
visited = NULL;
}
}
}
}
类定义:
class wdigraph {
public:
wdigraph(int =NO_NODES); // default constructor
~wdigraph() {}; // destructor
int get_size() { return size; } // returns size of digraph
void depth_first(int) const;// traverses graph using depth-first search
void print_graph() const; // prints adjacency matrix of digraph
private:
int size; // size of digraph
vector<char> label; // node labels
vector< vector<int> > adj_matrix; // adjacency matrix
};
谢谢!
您将在程序结束之前删除已visited
的对象。 回到起始顶点并不意味着您已经完成。 例如,对于V = {1,2,3}的图,E = {(1,2),(2,1),(1,3)}。
另外,请注意,您将v
用作输入参数,也用作for循环变量。
我看到几个问题:
下一行
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
应该更改为
if( adj_matrix[v][x] != 0 && visited[x] == false ) {
(您想递归仅在没有被访问过的顶点。)
另外,您正在for
循环中创建一个新变量v
来隐藏参数v
:这是合法的C ++,但这几乎总是一个糟糕的主意。
您可能需要考虑几件事。 首先是函数级静态变量通常不是一个好主意,您可以重新设计并使其成为常规变量(以额外的分配为代价)或实例成员并使它们保持活动状态。
该函数假定邻接矩阵为正方形,但未显示初始化代码,因此应进行检查。 可以通过使内循环条件adj_matrix[v].size()
(给定节点v
)来消除该假设,否则,如果该变量是不变的,则在该内循环之前添加一个断言: assert( adj_matrix[v].size() == adj_matrix.size() && "adj_matrix is not square!" );
-成员size
和自身的adj_matrix
大小也一样。
整个算法似乎比应有的复杂,从节点v开始的DFS具有以下一般形式:
dfs( v )
set visited[ v ]
operate on node (print node label...)
for each node reachable from v:
if not visited[ node ]:
dfs( node )
您的算法似乎是(以错误的方式)以相反的方向横穿了图形。 您将给定节点设置为visited
,然后尝试找到作为该边缘的起点的任何节点。 也就是说,您不是在尝试从v
到达节点,而是在尝试获取v
可以到达的节点。 如果是这种情况(即,如果目标正在打印在v
中收敛的所有路径),则必须注意不要两次击中同一条边,否则将陷入无限循环-> stackoverflow。
要看到您将以stackoverlow结尾,请考虑以下示例。 起始节点为1
。 创建visited
矢量并将位置1
标记为“访问”。 您发现树中有一个边(0,1),并触发了if: adj_matrix[0][1] != 0 && visited[1]
,因此您以递归方式输入起始节点为1
。 这次,您无需构造辅助数据,但要注意已visited[1]
,进入循环,找到相同的边并递归调用...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.