Graph data structure (4. Graph depth first traversal)

Depth-first traversal of Graphs

Presentation Form

  • Starting at a node, walk through the diagram without hitting the South Wall and without looking back.
  • Overall, the depth-first traversal for the number of tuples is similar, but you need a visited data to record whether the node has been visited or not, otherwise a lot of repetitive traversal will occur!

Matters needing attention

  • Since a graph does not necessarily contain only one connected component, it is important to take into account that the graph has multiple connected components when traversing.
  • The depth-first traversal of a graph consists of two cases:
    • Pre-order depth-first traversal (typically implemented, capable of handling most cases)
    • Post-order depth-first traversal
      • A subsequent tree-like traversal handles the current node in a regression process rather than a recursive one.
      • Subsequent depth-first traversal works wonderfully in some applications with directed graphs, as you will see later.
    • Both code implementations are very similar and very simple to the order and order traversal of numbers.

Application of depth-first traversal of Graphs

  • Count of connectivity components
  • Find if reachable between two points
  • Find a path between two points
  • Bipartite Detection
  • Find the bridge in the diagram
  • Finding cut points in a graph
  • Find the Hamilton Path
  • Topology sorting

code implementation

Functional implementation

// FileName: dfs.h


#include <vector>
#include <iostream>
#include <stack>

#include "../include/adj_list.h"
using namespace std;

class GraphDFS {
    AdjList adj_list;  //Diagram to save dfs
    vector<bool> visited;  //Stores flag s where nodes have been visited

    vector<int> pre_order;  //Stores the results of a depth preorder traversal of the graph
    vector<int> post_order;  //Stores the results of subsequent traversals of the graph's depth

    GraphDFS(const AdjList& adj_list_) {
         * GraphDFS Constructor that traverses depth first directly during the execution of the constructor
         * Params: 
         *     - adj_list_: Incoming graph represented by adjacency table
        adj_list = adj_list_;  //assignment
        visited = vector<bool>(adj_list.V(), false);  //Initialize all to false, meaning that none of the nodes have been traversed
        for (int i = 0; i < adj_list.E(); ++i) {  //Considering multiple connected components, traverse each node to dfs
            if (!visited[i])  //The current node has not been traversed yet, proceed with dfs

    void dfs(int v) {
         * Deep-first traversal from node v while maintaining the preceding and subsequent traversal arrays
         * Time Complexity: O(v_num+e_num)
         * Params:
         *     - v: Incoming Start Node
        pre_order.push_back(v);  //Maintain Pre-order Traversal Results
        visited[v] = true;  //Indicates that the current node has been traversed
        for (const int& u : adj_list.adj(v)) {  //Traversing adjacent nodes
            if (!visited[u]) {  //If you haven't traversed yet, continue with dfs
        post_order.push_back(v);  //Maintain subsequent traversal results (much like a binary tree's prefix, subsequent traversal hash)

    void dfsNoRecur(int v) {
         * Graph's prefix depth takes precedence over non-recursive implementations, requiring the help of an auxiliary data structure, the stack
         * The subsequent depth-first traversal of the graph is more complex than a non-recursive implementation, which is not possible here
         * Params:
         *     - v: Incoming Start Node
        stack<int> st;
        visited[v] = true;  //Initialize the stack and push the starting node into it, set its visited array to true
        while (!st.empty()) {
            //Remove the element, push in the result, see the adjacent points of the removed element, if not traversed, continue stacking, while maintaining the visited array of stack elements
            //Until the stack is empty, the algorithm ends
            int top =;
            for (const int &u: adj_list.adj(top)) {
                if (!visited[u]) {
                    visited[u] = true;

    vector<int> preOrder() {
        // Get the preorder traversal result
        return pre_order;

    vector<int> postOrder() {
        // Get subsequent traversal results
        return post_order;


functional testing

// FileName: dfs.cpp

#include <vector>
#include <iostream>

#include "../include/adj_list.h"
#include "../include/dfs.h"
using namespace std;

int main() {
    AdjList adj_list("../data/g2.txt");  //Notice here that node "5" is a separate connected component
    GraphDFS graph_dfs(adj_list);  //Initialize and precede and post-order depth-first traversal
    // Verify Pre-Sequence Traversal Results
    vector<int> pre_order = graph_dfs.preOrder();
    for (const int& e : pre_order) {
        cout << e << ", ";
    cout << endl;
    // Verify sequential traversal results
    vector<int> post_order = graph_dfs.postOrder();
    for (const int& e : post_order) {
        cout << e << ", ";
    cout << endl;
    return 0;

test result


  1. This section is relatively simple, but the application of dfs is very wide, its application will be described later.
  2. Since the two previously implemented interface diagrams are uniform, this code also applies to diagrams represented by adjacency matrices. You just need to change the class name, which is no longer implemented here.

Tags: C++ Algorithm data structure Graph Theory

Posted on Thu, 02 Sep 2021 23:43:53 -0400 by DJP1986