c++有向图深度优先搜索
我正在尝试为有向图编写方法 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
};
谢谢!
I am attempting to write a method DFS method for a directed graph. Right now I am running into a segmentation fault, and I am really unsure as to where it is. From what I understand of directed graphs I believe that my logic is right... but a fresh set of eyes would be a very nice help.
Here is my function:
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 definition:
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
};
thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您将在程序结束前删除
visited
。回到起始顶点并不意味着你已经完成了。
例如,对于 V = {1,2,3} 的图,E={(1,2),(2,1),(1,3)}。
另外,请注意您使用
v
作为输入参数以及 for 循环变量。You are deleting
visited
before the end of the program.Coming back to the starting vertex doesn't mean you finished.
For example, for the graph of V = {1,2,3}, E={(1,2),(2,1),(1,3)}.
Also, notice you are using
v
as the input parameter and also as the for-loop variable.您可能需要考虑一些事情。首先,函数级静态变量通常不是一个好主意,您可以重新设计并制作这些常规变量(以额外分配为代价)或实例成员,并使它们保持活动状态。
该函数假设邻接矩阵是方阵,但未显示初始化代码,因此应检查。可以通过设置内部循环条件
adj_matrix[v].size()
(给定节点v
)来删除假设,否则如果这是一个不变量,则添加一个断言在内循环之前:assert( adj_matrix[v].size() == adj_matrix.size() && "adj_matrix is not square!" );
-- 对于成员也是如此size
和adj_matrix
本身的大小。整个算法似乎比应有的更复杂,从节点 v 开始的 DFS 的一般形状为:
您的算法似乎(顺便说一下,这是错误的)以相反的方向遍历图。您将给定节点设置为
visited
,然后尝试找到作为该节点的边的起点的任何节点。也就是说,您尝试获取v
可到达的节点,而不是跟踪v
中可到达的节点。如果是这种情况(即,如果目标是打印在v
中汇聚的所有路径),那么您必须小心,不要两次击中同一条边,否则您将陷入无限循环 ->堆栈溢出。要看到您将以 stackoverlow 结束,请考虑此示例。起始节点是
1
。您创建visited
向量并将位置1
标记为已访问。你发现树中有一条边 (0,1),这会触发 if: adj_matrix[0][1] != 0 &&访问了[1],因此您再次递归输入,起始节点为1
。这次不构造辅助数据,而是备注visited[1]
,进入循环,找到相同的边,递归调用...There are a few things you might want to consider. The first is that function level static variables are not usually a good idea, you can probably redesign and make those either regular variables (at the cost of extra allocations) or instance members and keep them alive.
The function assumes that the adjacency matrix is square, but the initialization code is not shown, so it should be checked. The assumption can be removed by making the inner loop condition
adj_matrix[v].size()
(given a nodev
) or else if that is an invariant, add an assert before that inner loop:assert( adj_matrix[v].size() == adj_matrix.size() && "adj_matrix is not square!" );
--the same goes for the membersize
and the size of theadj_matrix
it self.The whole algorithm seems more complex than it should, a DFS starting at node v has the general shape of:
Your algorithm seems to be (incorrectly by the way) transversing the graph in the opposite direction. You set the given node as
visited
, and then try to locate any node that is the start point of an edge to that node. That is, instead of following nodes reachable fromv
, you are trying to get nodes for whichv
is reachable. If that is the case (i.e. if the objective is printing all paths that converge inv
) then you must be careful not to hit the same edge twice or you will end up in an infinite loop -> stackoverflow.To see that you will end with stackoverlow, consider this example. The start node is
1
. You create thevisited
vector and mark position1
as visited. You find that there is an edge (0,1) in the tree, and that triggers the if:adj_matrix[0][1] != 0 && visited[1]
, so you enter recursively with start node being1
again. This time you don't construct the auxiliary data, but remarkvisited[1]
, enter the loop, find the same edge and call recursively...我看到几个问题:
以下行
应更改为
(您只想在尚未访问过的顶点上递归。)
此外,您正在创建一个新变量
v
在for
循环中隐藏参数v
:这是合法的 C++,但它几乎总是一个糟糕的主意。I see a couple of problems:
The following line
should be changed to
(You want to recurse only on vertices that have not been visited already.)
Also, you're creating a new variable
v
in thefor
loop that hides the parameterv
: that's legal C++, but it's almost always a terrible idea.