Convert Directed Graph into a Tree


Strong data structures that depict connections among entities are directed graphs. To facilitate analysis or boost algorithmic effectiveness, it could be beneficial to transform a directed graph into a tree structure in some circumstances. In this post, we'll look at two CPP algorithmic approaches for turning a directed graph into a tree. We will go over the algorithm for each method, offer related code applications, and show off each approach's unique results.

Methods Used

  • Depth−First Search (DFS)

  • Topological Sorting

Depth−First Search (DFS)

The first approach traverses the graph using a depth−first search algorithm to create a tree structure. We establish edges between each unexplored node and its neighbouring nodes, starting from a root node, to make sure the resultant tree doesn't include any cycles. The algorithm works in the following way:

Algorithm

  • Choose a root node.

  • Create a blank tree.

  • Beginning at the root node, run a depth−first search.

  • Form an edge from the present node to every unexplored node you come across and recursively examine it.

  • Keep going until every node has been seen.

Example

#include <iostream>
#include <vector>

using namespace std;

class Graph {
private:
    vector<vector<int>> adjacencyList;

public:
    Graph(int numVertices) {
        adjacencyList.resize(numVertices);
    }

    void addEdge(int u, int v) {
        adjacencyList[u].push_back(v);
        adjacencyList[v].push_back(u);
    }

    int getNumVertices() {
        return adjacencyList.size();
    }

    vector<int> getAdjacentNodes(int node) {
        return adjacencyList[node];
    }
};

void convertGraphToTreeDFS(Graph& graph, int rootNode, vector<bool>& visited, vector<vector<int>>& tree) {
    visited[rootNode] = true;

    for (int adjacentNode : graph.getAdjacentNodes(rootNode)) {
        if (!visited[adjacentNode]) {
            tree[rootNode].push_back(adjacentNode);
            convertGraphToTreeDFS(graph, adjacentNode, visited, tree);
        }
    }
}

void convertGraphToTree(Graph& graph) {
    int numVertices = graph.getNumVertices();
    vector<bool> visited(numVertices, false);
    vector<vector<int>> tree(numVertices);

      int rootNode = 0;

    // Convert graph to tree using DFS
    convertGraphToTreeDFS(graph, rootNode, visited, tree);

    // Print tree structure
    for (int i = 0; i < numVertices; i++) {
        cout << "Node " << i << " -> ";
        for (int child : tree[i]) {
            cout << child << " ";
        }
        cout << endl;
    }
}

int main() {
    // Create an instance of the Graph class
    int numVertices = 5;
    Graph graph(numVertices);

    // Add edges to the graph
    graph.addEdge(0, 1);
    graph.addEdge(0, 2);
    graph.addEdge(1, 3);
    graph.addEdge(1, 4);

    // Call the function to convert the graph to a tree
    convertGraphToTree(graph);

    return 0;
}

Output

Node 0 -> 1 2 
Node 1 -> 3 4 
Node 2 -> 
Node 3 ->
Node 4 -> 

Topological Sorting

The third technique turns a directed graph into a tree by using the idea of topological sorting. By guaranteeing that the tree that is created is cycle−free, topological sorting ensures that it is an adequate depiction of the directed graph.

Algorithm

  • Order the directed graph in topological order.

  • Create a blank tree.

  • Build links between present nodes.

Example

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

using namespace std;

// Structure to represent a node in the tree
struct Node {
    int value;
    vector<Node*> children;
};

// Function to perform topological sorting using DFS
void topologicalSortDFS(int node, vector<vector<int>>& graph, vector<bool>& visited, stack<int>& stk) {
    visited[node] = true;

    for (int neighbor : graph[node]) {
        if (!visited[neighbor]) {
            topologicalSortDFS(neighbor, graph, visited, stk);
        }
    }

    stk.push(node);
}

// Function to convert directed graph into a tree
Node* convertToTree(vector<vector<int>>& graph) {
    int numVertices = graph.size();
    vector<bool> visited(numVertices, false);
    stack<int> stk;

    // Perform topological sorting
    for (int i = 0; i < numVertices; i++) {
        if (!visited[i]) {
            topologicalSortDFS(i, graph, visited, stk);
        }
    }

    // Create the tree
    unordered_map<int, Node*> nodes;
    Node* root = nullptr;

    while (!stk.empty()) {
        int nodeValue = stk.top();
        stk.pop();

        if (nodes.find(nodeValue) == nodes.end()) {
            Node* node = new Node{nodeValue, {}};
            nodes[nodeValue] = node;

            if (graph[nodeValue].empty()) {
                root = node;
            } else {
                for (int neighbor : graph[nodeValue]) {
                    if (nodes.find(neighbor) != nodes.end()) {
                        nodes[neighbor]->children.push_back(node);
                    }
                }
            }
        }
    }

    return root;
}

// Function to print the tree in pre-order traversal
void printTree(Node* root) {
    if (root == nullptr) {
        return;
    }

    cout << root->value << " ";

    for (Node* child : root->children) {
        printTree(child);
    }
}

int main() {
    // Example graph representation (adjacency list)
    vector<vector<int>> graph = {
        {},       // Node 0
        {0},      // Node 1
        {0},      // Node 2
        {1, 2},   // Node 3
        {2},      // Node 4
        {4},      // Node 5
        {3, 4},   // Node 6
    };

    // Convert directed graph into a tree
    Node* treeRoot = convertToTree(graph);

    // Print the tree in pre-order traversal
    cout << "Tree nodes: ";
    printTree(treeRoot);

    return 0;
}

Output

Tree nodes: 0 

Conclusion

This article talks about two approaches in C to changing a coordinated chart into a tree structure. The strategies investigated are Depth−First Look (DFS), and Topological Sorting. Each approach is clarified, followed by code cases that illustrate the usage and yield of each strategy. The article aims to provide perusers with a comprehensive understanding of how to convert a coordinated chart into a tree using distinctive calculations.

Updated on: 14-Jul-2023

1K+ Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements