c++有向图深度优先搜索

发布于 2024-10-05 23:07:41 字数 1338 浏览 2 评论 0原文

我正在尝试为有向图编写方法 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

灼痛 2024-10-12 23:07:41

您将在程序结束前删除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.

单身狗的梦 2024-10-12 23:07:41

您可能需要考虑一些事情。首先,函数级静态变量通常不是一个好主意,您可以重新设计并制作这些常规变量(以额外分配为代价)或实例成员,并使它们保持活动状态。

该函数假设邻接矩阵是方阵,但未显示初始化代码,因此应检查。可以通过设置内部循环条件 adj_matrix[v].size() (给定节点 v)来删除假设,否则如果这是一个不变量,则添加一个断言在内循环之前: assert( adj_matrix[v].size() == adj_matrix.size() && "adj_matrix is not square!" ); -- 对于成员也是如此sizeadj_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 中汇聚的所有路径),那么您必须小心,不要两次击中同一条边,否则您将陷入无限循环 ->堆栈溢出。

要看到您将以 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 node v) 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 member size and the size of the adj_matrix it self.

The whole algorithm seems more complex than it should, a DFS starting at node v has the general shape of:

dfs( v )
   set visited[ v ]
   operate on node (print node label...)
   for each node reachable from v:
      if not visited[ node ]:
         dfs( node )

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 from v, you are trying to get nodes for which v is reachable. If that is the case (i.e. if the objective is printing all paths that converge in v) 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 the visited vector and mark position 1 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 being 1 again. This time you don't construct the auxiliary data, but remark visited[1], enter the loop, find the same edge and call recursively...

耳钉梦 2024-10-12 23:07:41

我看到几个问题:

以下行

 if( adj_matrix[v][x] != 0 && visited[x] != false ) {

应更改为

 if( adj_matrix[v][x] != 0 && visited[x] == false ) {

(您只想在尚未访问过的顶点上递归。)

此外,您正在创建一个新变量 vfor 循环中隐藏参数 v:这是合法的 C++,但它几乎总是一个糟糕的主意。

I see a couple of problems:

The following line

 if( adj_matrix[v][x] != 0 && visited[x] != false ) {

should be changed to

 if( adj_matrix[v][x] != 0 && visited[x] == false ) {

(You want to recurse only on vertices that have not been visited already.)

Also, you're creating a new variable v in the for loop that hides the parameter v: that's legal C++, but it's almost always a terrible idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文