Skip to content

Instantly share code, notes, and snippets.

@Sand3r-
Last active March 28, 2020 12:23
Show Gist options
  • Save Sand3r-/0735e6b6a6a2a89e68c2bccdfe8eb160 to your computer and use it in GitHub Desktop.
Save Sand3r-/0735e6b6a6a2a89e68c2bccdfe8eb160 to your computer and use it in GitHub Desktop.
C++: Print tree to a dot/graphviz graph. Derive from this class and generate graph of a tree or a node hierarchy of your choice and save it to a .dot file.
#pragma once
#include <sstream>
#include <fstream>
#include <string>
// Inherit from this class, passing your node type as T
// template argument. Override GetNumChildren, GetChildNode
// and GetNodeName to provide a way of accessing node's name,
// its children and number of them.
template<typename T>
class AbstractGraphPrinter
{
public:
void WriteDot(const T* node, const char* filename)
{
std::stringstream ss;
ss << "digraph G {" << std::endl;
WriteRecursively(node, ss);
ss << "}" << std::endl;
std::ofstream file;
file.open(filename);
file << ss.rdbuf();
file.close();
}
virtual ~AbstractGraphPrinter() {};
protected:
// Returns number of node's children
virtual size_t GetNumChildren(const T* parent) = 0;
// Retrieves the ith child from a parent
virtual const T* GetChildNode(const T* parent, size_t child_id) = 0;
// Returns node's name, which will appear on the graph
virtual std::string GetNodeName(const T* node) = 0;
private:
void WriteRecursively(const T* node, std::stringstream& ss)
{
size_t children_num = GetNumChildren(node);
for(unsigned i = 0; i < children_num; i++)
{
const T* child = GetChildNode(node, i);
ss << "\"" << GetNodeName(node) << "\" -> \"" << GetNodeName(child) << "\"" << std::endl;
WriteRecursively(child, ss);
}
}
};
#include "GraphPrinter.h"
struct Node
{
std::string name;
Node* children;
size_t children_num;
};
class NodeGraphPrinter : public AbstractGraphPrinter<Node>
{
private:
size_t GetNumChildren(const Node* parent) final
{
return (size_t)parent->children_num;
}
const Node* GetChildNode(const Node* parent, size_t child_id) final
{
return &parent->children[child_id];
}
std::string GetNodeName(const Node* node) final
{
return node->name;
}
};
int main()
{
Node* root = GenerateTree(); // defined somewhere else
NodeGraphPrinter printer;
printer.WriteDot(root, "file.dot");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment