Graph implementation to be used for finding Cycles, Paths, closest path between two nodes, etc I am restudying graph theories and I want to write a Graph class that would allow me to implement those methods. Is there a better way of implementing a general Graph class? 

Main function:

int main() {

    using namespace GraphUtils;

    Graph&lt;char&gt; graph;

    Node&lt;char&gt; a('a');
    Node&lt;char&gt; b('b');
    Node&lt;char&gt; c('c');
    Node&lt;char&gt; d('d');
    Node&lt;char&gt; e('e');
    Node&lt;char&gt; f('f');

    graph.AddNode(a).AddNode(b).AddNode(c).AddNode(d).AddNode(e).AddNode(f);

    a.AddChild(f).AddChild(d);
    b.AddChild(c).AddChild(a);
    c.AddChild(d);
    e.AddChild(f);
    f.AddChild(b);

    graph.Print();


    if( !PathExist(graph, a, b)) {
        cout &lt;&lt; "ERR: a -&gt; b exists" &lt;&lt; endl;
    }

    if( !PathExist(graph, a, c)) {
        cout &lt;&lt; "ERR: a -&gt; c exists" &lt;&lt; endl;
    }

    if( PathExist(graph, a, e)) {
        cout &lt;&lt; "ERR: a -&gt; c doesn't exist" &lt;&lt; endl;
    }

    if( PathExist(graph, c, e)) {
        cout &lt;&lt; "ERR: c -&gt; e doesn't exist" &lt;&lt; endl;
    }
    if( !PathExist(graph, e, c)) {
        cout &lt;&lt; "ERR: e -&gt; c exists" &lt;&lt; endl;
    }
}


Class implementation, which is heavily pointer-oriented:

#include &lt;iostream&gt;
#include &lt;map&gt;
#include &lt;vector&gt;
#include &lt;queue&gt;


using std::map;
using std::vector;
using std::cout;
using std::endl;
using std::queue;

namespace GraphUtils {

template &lt;typename T&gt;
struct Node {
    T data;
    vector&lt;Node*&gt; children;

    Node() {}
    Node(T input): data(input) {}


    Node&amp; AddChild(Node&amp; input) {
        children.push_back(&amp;input);
        return *this;
    }

};


template &lt;typename T&gt;
bool operator&lt;(Node&lt;T&gt;&amp; lhs, Node&lt;T&gt;&amp; rhs) {
    return (lhs.data &lt; rhs.data);
}


template &lt;typename T&gt;
bool operator==(Node&lt;T&gt;&amp; lhs, Node&lt;T&gt;&amp; rhs) {
    return !(lhs.data &lt; rhs.data || lhs.data &gt; rhs.data);
}


template&lt;typename T&gt;
struct Graph {
    vector&lt;const Node&lt;T&gt;* &gt; nodes;

    Graph&amp; AddNode(const Node&lt;T&gt;&amp; input) {
        nodes.push_back(&amp;input);
        return *this;
    }

    void Print() {

        for(typename vector&lt;const Node&lt;T&gt;* &gt;::const_iterator iter = nodes.begin();
                iter != nodes.end();
                iter++)
        {
            cout &lt;&lt; (*iter)-&gt;data &lt;&lt; ":";

            for(typename vector&lt;Node&lt;T&gt;* &gt;::const_iterator child = (*iter)-&gt;children.begin();
                    child != (*iter)-&gt;children.end();
                    child++)
            {
                cout &lt;&lt; (*child)-&gt;data &lt;&lt; ", ";

            }

            cout &lt;&lt; endl;
        }
    }
};


// using BFS to determine if path exists
template&lt;typename T&gt;
bool PathExist(Graph&lt;T&gt;&amp; graph, Node&lt;T&gt;&amp; a, Node&lt;T&gt;&amp; b) {

    map&lt;const Node&lt;T&gt;* , bool&gt; t_visited;
    queue&lt;Node&lt;T&gt;* &gt; t_queue;

    for(typename vector&lt;const Node&lt;T&gt;* &gt;::const_iterator iter = graph.nodes.begin();
            iter != graph.nodes.end(); iter++)
    {
        t_visited[*iter] = false;
    }

    t_queue.push(&amp;a);

    Node&lt;T&gt;* t_node;
    while(!t_queue.empty()) {

        // get the top object
        t_node = t_queue.front();
        t_queue.pop();

        // set visited
        t_visited[t_node] = true;

        // node doesn't have the == operator
        if(*t_node == b) return true;

        // for each ot it's children
        for(typename vector&lt;Node&lt;T&gt;* &gt;::iterator iter = t_node-&gt;children.begin();
                iter !=  t_node-&gt;children.end(); iter++)
        {
            // if item has not been visited
            if(!t_visited[(*iter)]) {
                t_queue.push((*iter));
            }
        }
    }

    return false;
}





};
That depends on what is good in some sense. It's a pretty standard adjacency list implementation, and it's nothing wrong with that. Whether it's good depends on what query you gonna ask the data structure. If doing path search or minimal spanning tree for sparse graph that is good. If you want to do some clustering, then maybe an adjacency matrix is better.

On the API level, I like that chaining add methods. It's nice and easy to use. Storing pointer to aliases avoided the problem of memory leakage, but it makes the programmer feel a bit silly to declare a variable for each node, with only one character in it. What if the number of nodes dynamically grows, which is one of the strength of using an adjacency list? Why can't I do like graph.AddNode('a')? And add child by graph.get('a').AddChild('b') or something. 

Also if the node local variables goes out of scope, the graph must die or in danger of facing segmentation fault, or even some security issues. Not very flexible.