You can use vector in node as an adjacency list.
class node { int value; vector<node*> neighbors; };
If the graph is known at compile time, you can use array , but it is "a bit" more complicated. If you only know the size of the graph (at compile time), you can do something like this.
template<unsigned int N> class graph { array<node, N> nodes; }
To add a neighbor, you do something like this (don't forget numbering from scratch):
nodes[i].neighbors.push_back(nodes+j); //or &nodes[j]
Of course, you can make a non-pointer adjacency list and work on a table. Than you have a vector<int> in node and you click on the number of neighbors. With both representations of the graph, you can implement all the algorithms that use the adjacency list.
And finally, I could add. Some use list instead of a vector because deletion happens in O (1) . Mistake. For most algorithms, the order in the adjacency list is not important. Thus, you can erase any element from a vector in O (1) . Just replace it with the last element, pop_back is O (1) complexity. Something like that:
if(i != number_of_last_element_in_list)
Concrete example (you have a vector in node, C ++ 11 (!)):
//creation of nodes, as previously constexpr unsigned int N = 3; array<node,N> nodes; //or array<node, 3> nodes; //creating edge (adding neighbors), in the constructor, or somewhere nodes[0].neighbors = {&nodes[1]}; nodes[1].neighbors = {&nodes[0], &nodes[1]}; //adding runtime, i,j from user, eg. i = 2, j = 0 nodes[i].neighbors.push_back(&nodes[j]); //nodes[2].neighbors = {&nodes[0]};
I think this is understandable. From 0 you can go to 1 , from 1 to 0 and to yourself, and (as, for example) from 2 to 0 . He oriented the count. If you want to redirect, you must add node addresses to both nodes. You can use numbers instead of pointers. vector<unsigned int> in the class node and discarding the return numbers, with no addresses.
As we know, you do not need to use pointers. Here is an example of this.
When the number of vertices can change, you can use a vector of nodes ( vector<node> ) instead of an array and just resize . The rest remains unchanged. For example:
vector<node> nodes(n); //you have n nodes nodes.emplace_back(); //you added new node, or .resize(n+1) //here is place to runtime graph generate //as previously, i,j from user, but now you have 'vector<unsigned int>' in node nodes[i].neighbors.push_back(j);
But you cannot erase a node, this breaks the numbering! If you want to erase something, you should use a list of ( list<node*> ) pointers. Otherwise, you must save non-existent vertices. Here, order matters!
Regarding the string nodes.emplace_back(); //adding node nodes.emplace_back(); //adding node , it is safe with a chart without pointers. If you want to use pointer pointers, you should mainly not resize the graph. You can accidentally change the address of some nodes by adding a vertex when vector is copied to a new location (out of space).
One way to handle this is to use reserve , although you need to know the maximum chart size! But in fact, I urge you not to use vector to store vertices when you use pointers. If you do not know the implementation, managing your own memory (smart pointers like shared_ptr or just new ) can be safer.
node* const graph = new node[size];
Using vector as an adjacency list is always great ! There is no way to change the node address.