Depth-first graph traversal

algorithm, c++, graph, segmentation-fault

Solution

So I figured out my problem using the following algorithm. Hope this will help anyone having the same problem.

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
}

Problem

I'm trying to print a depth-first traversal. I have the following code which continues to give me a seg fault. It seems to be occurring when I try to print the last vertex in the graph. The first traversal I do starting at vertex 'A', works as it should. But when I try to do a depth-first print starting from D, I get the seg fault. Here is my source code: Here is my original source code: ``` 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; } ``` This is the header file and the constructor: ``` // 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; } } } ``` Here is the main routine: ``` #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); } ``` This is the output that I am getting. The graph shows the weight of each edge. A '-' means there is no edge. ``` 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) ``` If I remove the `u = i` code from the for loop, then my program works fine. Here is my output when I try to print the third graph. Notice, my traversal is not traveling correctly.

Original source