Topics
Depth-First Search (DFS) algorithm for traversing/searching tree or graph data structure. Starts at root/arbitrary node, explores as far as possible along each branch before backtracking. Goes “deep” first.
Core mechanic: backtracking. Reach vertex with no unvisited neighbors? Step back to previous vertex. Explore next available path. Systematically explores/backtracks to visit all reachable vertices.
Common implementations:
- Recursion: Intuitive. Function call stack acts as implicit stack. Mark current vertex vvisited. For each neighboruofv, if unvisited, recursive calldfs(u). Backtracking natural when call returns
- Iteration: Explicit dfs using stack. Push start node. While stack not empty: Pop node. If unvisited: Mark visited, process. Push all unvisited neighbors onto stack. Avoids deep recursion limits.
Graphs with cycles: Must track visited vertices to avoid infinite loops. Use boolean array or hash set.
DFS traversal order concepts:
- pre-order traversal: Process vertex before recursive calls to neighbors. Typical basic DFS order. Reflects the order in which nodes are first discovered
- post-order traversal: Process vertex after recursive calls for all neighbors complete. Node processed only after entire subtree explored
Post-ordering significant in algorithms like topological sorting and finding connected components in undirected graphs. Aggregates descendant info before ancestor. Pre-ordering sufficient for basic reachability/path finding.
Time Complexity: 
Space Complexity:  (visited array and recursion stack)
Implementation (Recursive)
vector<vector<int>> adj;
vector<bool> visited;
vector<int> dfs_order;  // To store the traversal order (pre-order)
 
void dfs(int u) {
    visited[u] = true;       // Mark current node as visited
    dfs_order.push_back(u); // Process node (add to pre-order traversal list)
 
    for (int v : adj[u]) {
        if (!visited[v]) {
            dfs(v);
        }
    }
    // Post-order processing could be done here after the loop
}
 
int main() {
    int n, m;
    cin >> n >> m;
 
    adj.resize(n);
    visited.resize(n, false);
 
    for (int i = 0; i < m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u); // undirected graph case
    }
 
    // handles disconnected graphs
    for (int i = 0; i < n; ++i) {
        if (!visited[i]) {
            dfs(i); // Start DFS for a new component
        }
    }
 
 
    for (int node : dfs_order) {
        cout << node << " ";
    }
    cout << endl;
 
    return 0;
}