I've been trying to create a directed graph following https://www.youtube.com/watch?v=V_TulH374hw
class Digraph {
public:
Digraph();
void addNode(Node);
void addEdge(Edge);
void print();
private:
//This is a vector which contains a node source and a vector of node destinations
vector< tuple< Node, vector<Node>>> nodes;
};
but after I add 2 nodes and a Edge it seems like the vector with the destinations is beeing emptied
void Digraph::addEdge(Edge e){
Node src = e.getSrc();
Node dest = e.getDest();
for(auto node : nodes){
if(get<0>(node).getName() == src.getName()){
get<1>(node).push_back(dest);
//cout << "added conection " << get<0>(node).getName() << " -> " << get<1>(node).back().getName() << " now " << get<0>(node).getName() << " has " << get<1>(node).size() << " destinations" <<"\n";
return;
}
}
cout << "node " << src.getName() << " does not exist \n";
return;
}
void Digraph::print(){
for(auto node : nodes){
get<0>(node).print();
cout << " has " << get<1>(node).size() << " destinations";
cout << "\n";
for(auto destination : get<1>(node)){
cout << "\t->";
destination.print();
cout << "\n";
}
}
}
In main.cpp I add the nodes and the edge
graph.addNode(NY);
graph.addNode(CHICAGO);
graph.addEdge(road);
graph.print();
It ends up adding the edge succesfully but when it prints the final result it does not recognize the edge it just added
added conection NY -> Chicago now NY has 1 destinations
NY has 0 destinations
Chicago has 0 destinations
When tried with more Nodes and Edges I realized it never adds more than one Edge, maybe it has to do with how i defined the class? vectors is not the choice?
CodePudding user response:
Your auto
in the for loop needs to be a reference (auto&
), and after the code I'll tell you why.
void Digraph::addEdge(Edge e){
Node src = e.getSrc();
Node dest = e.getDest();
// use references here
for(auto& node : nodes){
if(get<0>(node).getName() == src.getName()){
// now this modifies the original, not a copy
get<1>(node).push_back(dest);
//cout << "added conection " << get<0>(node).getName() << " -> " << get<1>(node).back().getName() << " now " << get<0>(node).getName() << " has " << get<1>(node).size() << " destinations" <<"\n";
return;
}
}
cout << "node " << src.getName() << " does not exist \n";
return;
}
The entire point of this function is to change the nodes in some way. If you iterate over them with for (auto node : nodes)
you are getting a copy of each node. It's the same as Node node : nodes
, the auto
doesn't make a difference. You then call push_back
on this copy, which gets destroyed as soon as the next loop iteration comes up.
Effectively, your original stays entirely untouched since you only take copies of it's member nodes, not references.
If you use a reference here like I did, you take a reference to each node in the nodes
vector, and modify the reference, which modifies the original.