我正在尝试为有向图编写方法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
};
谢谢!
答案 0 :(得分:3)
您正在程序结束前删除visited
。
回到起始顶点并不意味着你完成了。
例如,对于V = {1,2,3}的图,E = {(1,2),(2,1),(1,3)}。
另外,请注意您使用v
作为输入参数以及for-loop变量。
答案 1 :(得分:2)
我看到了几个问题:
以下一行
if( adj_matrix[v][x] != 0 && visited[x] != false ) {
应改为
if( adj_matrix[v][x] != 0 && visited[x] == false ) {
(您只想在已经访问 not 的顶点上进行递归。)
此外,您在隐藏参数v
的{{1}}循环中创建了一个新变量for
:这是合法的C ++,但它几乎总是一个糟糕的主意。
答案 2 :(得分:2)
您可能需要考虑一些事项。第一个是函数级静态变量通常不是一个好主意,你可以重新设计并制作常规变量(以额外分配为代价)或实例成员并保持它们存活。
该函数假定邻接矩阵是正方形,但未显示初始化代码,因此应进行检查。可以通过使内循环条件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
中的路径),那么你必须小心不要两次击中相同的边缘,否则你将以无限循环结束 - &gt;堆栈溢出。
要了解您将以stackoverlow结束,请考虑此示例。起始节点为1
。您创建visited
向量并将位置1
标记为已访问。您发现树中有一个边(0,1),并触发if:adj_matrix[0][1] != 0 && visited[1]
,因此您再次以起始节点1
递归输入。这次你不构造辅助数据,但是注释visited[1]
,进入循环,找到相同的边缘并递归调用...