深度优先图遍历

Posted

技术标签:

【中文标题】深度优先图遍历【英文标题】:Depth-first graph traversal 【发布时间】:2013-11-29 20:26:54 【问题描述】:

我正在尝试打印深度优先遍历。我有以下代码继续给我一个段错误。当我尝试打印图中的最后一个顶点时,它似乎正在发生。我从顶点'A'开始的第一次遍历,按它应该的方式工作。但是当我尝试从 D 开始进行深度优先打印时,我得到了段错误。这是我的源代码:

这是我的原始源代码:

void wdigraph::depth_first(int u) const 

  bool found = false;

  vector<bool> visited;             // create a boolean vector
  for(int i =0; i < size; i++)      // the size of the graph
    visited.push_back(false);       // to mark when a node has been visited

  stack<int> depth_first;           // used to hold vertices that have been visited
  visited[u] = true;                // mark as visited
  cout << label[u];                 // print first vertex
  depth_first.push(u);              // put first vertex on stack

  while(!all_visited(visited))     // continue until all vertices have been visited
    found = false;

    for(unsigned i = 0; i < visited.size() && !found; i++) 
      if(adj_matrix[u][i] != 0 && !visited[i])   // found next vertex
        cout << "->" << label[i];   // print vertex
        visited[i] = true;          // mark vertex as visited
        depth_first.push(i);        // push vertx onto stack
        found = true;               // set found = true to end for loop
        u = i;
      //endif
    //endfor  

    if(found == false)             // no available neighbors
      u = depth_first.top();        // get top of stack
      depth_first.pop();            // pop from stack
    //endif
  //endwhile 

  cout << '\n';


void wdigraph::print_graph() const 
  cout << '\n';
  cout << "No of Nodes = " << size << endl;

  cout << "\nAdjacency Matrix\n" << endl;

  cout << "  |";
  for(int i = 0; i < size; i++)
    cout << "  " << label[i];

  cout << '\n';

  cout << "--|";
  for(int i = 0; i < size; i++)
    cout << "---";
  cout << '\n';

  for(int i = 0; i < size; i++) 
    cout << label[i] << " |";

    for(int j = 0; j < size; j++) 
      if(adj_matrix[i][j] != 0)
        cout << " " << setw(2) << right << adj_matrix[i][j];
      else
        cout << "  -";
    //endjfor

      cout << '\n';

      if(i != size-1)
        cout << "  |" << endl;
  //endifor

  cout << '\n';

bool all_visited(vector<bool> &v) 
  for(unsigned i = 0; i < v.size(); i++)
    if(v[i] == false)
      return false;

  return true;

这是头文件和构造函数:

// definition of weighted digraph

#define NO_NODES   1    // default size for no of nodes in digraph
#define LINK_PROB  0.25 // prob of having direct link between nodes
#define MAX_WEIGHT 10   // max weight factor for links
class wdigraph 
public:
    wdigraph ( int = NO_NODES );            // default constructor
    ~wdigraph ( )  ;                      // destructor
    int get_size ( ) const  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
;

// default class constructor

wdigraph :: wdigraph ( int n ) : size ( n )

    // allocate dynamic memory

    label = vector < char > ( size );
    adj_matrix = vector < vector < int > > ( size );
    for ( int i = 0; i < size; i++ )
        adj_matrix [ i ] = vector < int > ( size );

    // assign labels to each node

    label [ 0 ] = 'A';
    for ( int i = 1; i < size; i++ )
        label [ i ] = label [ i - 1 ] + 1;

    // determine weights for links between nodes randomly
    // and build adjacency matrix

    srand ( 1 );
    for ( int i = 0; i < size; i++ ) 
        adj_matrix [ i ] [ i ] = 0;
        bool flag = false;
        for ( int j = 0; j < size; j++ ) 
            if ( j == i ) continue;
            double r = ( double ) rand ( ) / RAND_MAX;
            adj_matrix [ i ] [ j ] =
                ( r <= LINK_PROB ) ? rand ( ) % MAX_WEIGHT + 1 : 0;
            if ( adj_matrix [ i ] [ j ] > 0 ) flag = true;
        

        // if node is not connected to any other node, then
        // connect this node to random node

        if ( size > 1 && !flag ) 
            int k; while ( ( k = rand ( ) % size ) == i ) ;
            adj_matrix [ i ] [ k ] = rand ( ) % MAX_WEIGHT + 1;
        
    

这里是主程序:

#define M  3   // print every M-th node's path when traversing
#define N2 5   // number of nodes in second graph
#define N3 20  // number of nodes in third graph


void proc_graph(wdigraph&);       // function declaration

int main() 
  // create three weighted digraphs
  wdigraph graph1(NO_NODES);
  wdigraph graph2(N2);
  wdigraph graph3(N3);

  //proc_graph(graph1);   // print first graph
  proc_graph(graph2);   // print first graph
  //proc_graph(graph3);   // print first graph

  return 0;


void proc_graph(wdigraph &g) 
  cout << '\n';
  cout << "A Weighted Digraph" << endl;    // print header
  cout << "__________________" << endl;    // print header underline

  g.print_graph();                         // print graph

  cout << "Paths by Depth-First Search" << endl;
  for(int i = 0; i < g.get_size(); i += M)
    g.depth_first(i);

这是我得到的输出。该图显示了每条边的权重。 '-' 表示没有边缘。

A Weighted Digraph
__________________

No of Nodes = 5

Adjacency Matrix

  |  A  B  C  D  E
--|---------------
A |  -  -  -  6  -
  |
B |  -  -  8  -  -
  |
C |  7  -  -  -  -
  |
D |  7  9 10  -  1
  |
E |  4  - 10  -  -

Paths by Depth-First Search
A->D->B->C->E
Segmentation fault (core dumped)

如果我从 for 循环中删除 u = i 代码,那么我的程序可以正常工作。这是我尝试打印第三张图时的输出。请注意,我的遍历没有正确运行。

【问题讨论】:

堆栈跟踪是什么样的? 我正在使用 putty 编译和执行。除了“分段错误(核心转储)之外,我没有得到任何堆栈跟踪。 使用 -g 选项编译并运行合适的调试器,例如,在使用 gccclang 编译时,gdb。要么直接在程序上执行,要么在内核上运行调试器。 @Kevin 你可以在答案部分写下你的答案。这样解决方案更清晰,已知存在,并且您得到一些分数 【参考方案1】:

所以我使用以下算法解决了我的问题。希望这对遇到同样问题的人有所帮助。

push current onto stack
mark as visited
print current
while (stack is not empty) 
  current = stack top
  of N neighbors of current, find first that hasnt been visited
    if such neighbor exists
      add to stack
      mark as visited
      print
    if no neighbor exists
      pop from stack

【讨论】:

以上是关于深度优先图遍历的主要内容,如果未能解决你的问题,请参考以下文章

数据结构—深度优先遍历广度优先遍历图遍历算法的应用

c语言图的遍历,邻接表存储,深度,广度优先遍历

图 - 深度优先遍历

深度优先图遍历

python实现图广度优先遍历深度优先遍历

数据结构—— 图:图的遍历