HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Graph represented by an adjacency matrix in C++

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
representedadjacencymatrixgraph

Problem

I'm working on my data structures knowledge and wanted to create a graph with a small DFS driver which simply prints the nodes as it visits them. Here's my graph class:

#ifndef GRAPH_H_
#define GRAPH_H_

#include 
#include 
#include 
#include 
#include 

template 
class Graph {
  public:
    Graph(bool directed) : directed{directed}, adj_matrix{} {}
    ~Graph() {}
    void add_edge(const T& start, const T& end) {
      adj_matrix[start][end] = true;
      adj_matrix[start][start] = false;
      adj_matrix[end][end] = false;
      adj_matrix[end][start] = directed ? false : true;
    }

    void DFS(T const *start=nullptr) const {
      if(!adj_matrix.size())
        return;
      if(start==nullptr) {
        DFS_helper(get_random_node());
      } else {
        DFS_helper(*start);
      }
    }

    void DFS_helper(const T& start) const {
      std::unordered_set visited;
      std::stack s;
      s.push(start);
      while(!s.empty()) {
        T top = s.top();
        s.pop();
        // If top is unvisited
        if(visited.find(top) == std::end(visited)) {
          // visit it
          visited.insert(top);
          std::cout  get_adjacent_nodes(const T& v) const {
        std::vector adj;
        for(const auto& pair: adj_matrix.at(v)) {
            T neighbor = pair.first;
            bool is_neighbor = pair.second;
            if(is_neighbor) {
                adj.push_back(neighbor);
            }
        }
        return adj;
    }
    T get_random_node() const {
      auto random_it = std::next(std::begin(adj_matrix), std::rand() % (adj_matrix.size()-1));
      return random_it->first;
    }
    const bool directed;
    std::unordered_map> adj_matrix;
};

#endif //GRAPH_H_


And here's my driver (inspired from this Wikipedia image):

```
#include
#include "graph.h"

int main() {
bool directed = false;
Graph g(directed);
g.add_edge('A', 'B');
g.add_edge('B', 'D');
g.add_edge('A', 'E');
g.add_edge('E', 'F');
g.add_edge('A', 'C');

Solution

Your code looks reasonable, yet I have one suggestion: decouple algorithms from output:

std::vector DFS(T const *start=nullptr) const {
    if(!adj_matrix.size())
        return std::vector();
    if(start==nullptr) {
        return DFS_helper(get_random_node());
    } else {
        return DFS_helper(*start);
    }
}

std::vector DFS_helper(const T& start) const {
    std::unordered_set visited;
    std::unordered_map parents {{start, nullptr}};
    std::stack s;
    std::vector nodes;
    s.push(start);
    while(!s.empty()) {
        T top = s.top();
        s.pop();
        // If top is unvisited
        if(visited.find(top) == std::end(visited)) {
            // visit it
            visited.insert(top);
            nodes.push_back(top);
            for(const auto& adj_node: get_adjacent_nodes(top)) {
                s.push(adj_node);
                parents[adj_node] = ⊤
            }
        }
    }
    return nodes;
}


Suppose what happens if your friend needs to run your DFS on a large graph. Most definitely, he or she will be overwhelmed with all the output. So, let the DFS return silently a list of visited nodes; only after that print the nodes if need be.

Code Snippets

std::vector<T> DFS(T const *start=nullptr) const {
    if(!adj_matrix.size())
        return std::vector<T>();
    if(start==nullptr) {
        return DFS_helper(get_random_node());
    } else {
        return DFS_helper(*start);
    }
}

std::vector<T> DFS_helper(const T& start) const {
    std::unordered_set<T> visited;
    std::unordered_map<T, T*> parents {{start, nullptr}};
    std::stack<T> s;
    std::vector<T> nodes;
    s.push(start);
    while(!s.empty()) {
        T top = s.top();
        s.pop();
        // If top is unvisited
        if(visited.find(top) == std::end(visited)) {
            // visit it
            visited.insert(top);
            nodes.push_back(top);
            for(const auto& adj_node: get_adjacent_nodes(top)) {
                s.push(adj_node);
                parents[adj_node] = &top;
            }
        }
    }
    return nodes;
}

Context

StackExchange Code Review Q#142861, answer score: 3

Revisions (0)

No revisions yet.