I was trying to implement some Graph Algorithms so continuing by testing I received an error in GNU C++ compiler (Segmentation Fault). In Visual Studio I saw the cause is "vector iterators incompatible". But how this happens? The error is thrown in shortestPathBFS function in the line "getName()" when I try to access a field of visitor object. Visitor is an element of Vertice* queue, so it must not depend on queue iterator in my opinion. If you can explain me why, I will be appreciated.
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <string>
#include <iostream>
using namespace std;
//#define traverse(container,iterator) \
//for(typeof(container.begin()) iterator = container.begin(); iterator != container.end(); iterator++)
class Edge;
class Vertice
{
private:
string name;
vector<Edge*> incidences;
bool visited;
public:
Vertice() {name = "NULL"; visited = false;}
Vertice(string name) {this->name = name; visited = false;}
void setName(string name) {this->name = name;}
string getName() {return name;}
bool isVisited() {return visited;}
void setVisited() {visited = true;}
void setUnvisited() {visited = false;}
void connectTo(Vertice*);
void connectTo(Vertice*,int);
void printNeighbors();
vector<Vertice*> getNeighbors();
};
class Edge
{
private:
int cost;
Vertice *start,*end;
public:
friend class Vertice;
Edge() {cost = 0;}
Edge(Vertice * start, Vertice * end) {this->start = start; this->end = end;}
Edge(Vertice * start, Vertice * end, int cost)
{this->start = start; this->end = end; this->cost = cost;}
Vertice* getEnd() {return end;}
Vertice* getStart() {return start;}
};
void Vertice::connectTo(Vertice * w)
{
incidences.push_back(new Edge(this,w));
}
void Vertice::connectTo(Vertice* w,int cost)
{
incidences.push_back(new Edge(this,w,cost));
}
vector<Vertice*> Vertice::getNeighbors()
{
vector<Vertice*> temp;
for(vector<Edge*>::iterator it = incidences.begin(); it != incidences.end(); it++)
{
temp.push_back((*it)->getEnd());
}
return temp;
}
void Vertice::printNeighbors()
{
for (vector<Edge*>::iterator i=incidences.begin(); i!= incidences.end(); i++)
{
cout<<(*i)->start->getName()<<"--"<<(*i)->cost<<"--"<<(*i)->end->getName()<<endl;
}
}
class Graph
{
public:
// using set for non-comparable elements are not good
// but this is for exercising
set<Vertice *> vertices;
public:
void initGraph()
{
Vertice *v;
v = new Vertice("IST");vertices.insert(v);
v = new Vertice("ANK");vertices.insert(v);
v = new Vertice("IZM");vertices.insert(v);
v = new Vertice("BER");vertices.insert(v);
v = new Vertice("TOR");vertices.insert(v);
v = new Vertice("BEJ");vertices.insert(v);
v = new Vertice("PER");vertices.insert(v);
(*findByName("IST"))->connectTo(*findByName("ANK"),10);
(*findByName("IST"))->connectTo(*findByName("IZM"),5);
(*findByName("IST"))->connectTo(*findByName("BER"),61);
(*findByName("IZM"))->connectTo(*findByName("ANK"),3);
(*findByName("IZM"))->connectTo(*findByName("TOR"),98);
(*findByName("IZM"))->connectTo(*findByName("BER"),70);
(*findByName("BER"))->connectTo(*findByName("ANK"),59);
(*findByName("BER"))->connectTo(*findByName("TOR"),91);
(*findByName("ANK"))->connectTo(*findByName("PER"),77);
(*findByName("ANK"))->connectTo(*findByName("BEJ"),151);
(*findByName("BEJ"))->connectTo(*findByName("TOR"),48);
(*findByName("TOR"))->connectTo(*findByName("ANK"),100);
(*findByName("PER"))->connectTo(*findByName("BEJ"),162);
(*findByName("TOR"))->connectTo(*findByName("PER"),190);
(*findByName("BEJ"))->connectTo(*findByName("PER"),163);
}
set<Vertice*>::iterator findByName(string name)
{
for(set<Vertice*>::iterator it = vertices.begin(); it != vertices.end(); it++)
{
if ((*it)->getName() == name)
{
return it;
}
}
return vertices.end();
}
int shortestPathBFS(Vertice * start, Vertice * finish)
{
queue<Vertice *> q;
q.push(start);
Vertice *visitor;
while(!q.empty())
{
visitor = q.front();q.pop();
visitor->setVisited();
cout<<"BFS : "<<visitor->getName()<<endl;
if (visitor->getName() == finish->getName())
{
break;
}
for(vector<Vertice*>::iterator it = (visitor->getNeighbors()).begin(); it != (visitor->getNeighbors()).end(); it++ )
{
if (!(*it)->isVisited())
{
q.push((*it));
}
}
}
return 0;
}
void printAll()
{
for(set<Vertice*>::iterator it = vertices.begin(); it != vertices.end(); it++)
{
(*it)->printNeighbors();
}
}
};
int main(int argc, char **argv)
{
Graph g;
g.initGraph();
g.printAll();
g.shortestPathBFS(*(g.findByName("IST")),*(g.findByName("PER")));
return 0;
}
The culprit is this line in Graph::shortestPathBFS:
for(vector<Vertice*>::iterator it = (visitor->getNeighbors()).begin(); it != (visitor->getNeighbors()).end(); it++ )
The problem is that you cannot compare iterators from two different containers (even if the containers are the same type), but visitor->getNeighbors() returns a new object each time it is invoked. Consequently, it is initialized from one object then compared to an iterator from a different object.
Rewrite the loop as:
vector<Vertice*> neighbors = visitor->getNeighbors();
for(vector<Vertice*>::iterator it = neighbors.begin(); it != neighbors.end(); ++it)
{
if (!(*it)->isVisited())
{
q.push((*it));
}
}
Related
I'm trying to build a graph class where the graph is represented by adjacency lists. The graph itself is a vector of pointers where each pointer points to a linked list of nodes. For whatever reason, when I use the print graph function the program outputs nothing. Can anyone show me what I am doing wrong and perhaps where my misunderstanding of pointers is? Thanks in advance!
#include <array>
#include <vector>
#include <tuple>
#include <unordered_map>
class Node
{
public:
int vertex;
int value;
Node* next;
Node(int ver)
{
vertex = ver;
};
};
class Graph
{
public:
int n_nodes;
std::unordered_map<int,Node*> graph;
Graph(int n)
{
n_nodes = n;
for(int i=0;i<n;i++)
{
graph.insert({i,nullptr});
};
};
void add_edge(int src,int des,int val)
{
Node node_des = Node(des);
node_des.value = val;
node_des.next = graph[src];
graph[src] = &node_des;
Node node_src = Node(src);
node_src.value = val;
node_src.next = graph[des];
graph[des] = &node_src;
};
void print_graph()
{
for(int i =0; i<n_nodes;i++)
{
std::string str = "Head "+std::to_string(i);
Node node = *graph[i];
while (&node != nullptr)
{
str=str+" -> "+std::to_string(node.vertex);
node = *(node.next);
};
std::cout<<str<<std::endl;
};
};
};
int main()
{
Graph g = Graph(6);
g.add_edge(0,1,3);
g.add_edge(2,1,4);
g.add_edge(0,4,1);
g.add_edge(4,5,6);
g.add_edge(5,3,2);
g.add_edge(4,3,3);
g.add_edge(3,2,5);
g.add_edge(4,1,1);
g.add_edge(3,1,2);
g.print_graph();
return 0;
}```
If it´s possible, you may just use vector of vector instead of linked lists and not use pointers at all. Because memory cache some insertions in vectors operations may be faster than linked lists, a structure like :
struct Node2 {
int vertex;
int value;
};
struct Edge2 {
int src, des, value;
};
struct Graph2 {
int n_nodes;
std::vector<std::vector<Node2>> graph;
void add_edge(Edge2 edge) {
graph[edge.src].emplace_back(edge.des, edge.value);
graph[edge.des].emplace_back(edge.src, edge.value);
}
void add_edge(std::initializer_list<Edge2> edges)
{
std::for_each(edges.begin(), edges.end(), [this](auto &e) { add_edge(e); });
};
}
Endup bening easier and faster than linked lists;
https://quick-bench.com/q/cmX2-2IYA873TR4qn5aV4ijjUQo
Made these changes thanks to #drescherjm. The issue was that I had created a local variable and referenced its address instead of explicitly creating a pointer and setting it to a new node instance where the object's lifetime is dynamically controlled.
#include <bits/stdc++.h>
#include <array>
#include <vector>
#include <tuple>
#include <unordered_map>
class Node
{
public:
int vertex;
int value;
Node* next;
Node(int ver)
{
vertex = ver;
};
};
class Graph
{
public:
int n_nodes;
std::unordered_map<int,Node*> graph;
Graph(int n)
{
n_nodes = n;
for(int i=0;i<n;i++)
{
graph.insert({i,nullptr});
};
};
void add_edge(int src,int des,int val)
{
Node * node_des = new Node(des);
node_des->value = val;
node_des->next = graph[src];
graph[src] = node_des;
Node * node_src = new Node(src);
node_src->value = val;
node_src->next = graph[des];
graph[des] = node_src;
};
void print_graph()
{
for(int i =0; i<n_nodes;i++)
{
std::string str = "Head "+std::to_string(i);
Node * node_ptr = graph[i];
while (node_ptr != nullptr)
{
str=str+" -> "+std::to_string(node_ptr->vertex);
node_ptr = node_ptr->next;
};
std::cout<<str<<std::endl;
};
};
};
int main()
{
Graph g = Graph(6);
g.add_edge(0,1,3);
g.add_edge(2,1,4);
g.add_edge(0,4,1);
g.add_edge(4,5,6);
g.add_edge(5,3,2);
g.add_edge(4,3,3);
g.add_edge(3,2,5);
g.add_edge(4,1,1);
g.add_edge(3,1,2);
g.print_graph();
return 0;
}
basically, I want to implement document type converter. I've designed pretty straight-forward solution:
DocTypeParser : Parser will converts file into tree structure of nodes, representing different elements (headers, lists, bold texts, ...)
DocTypePrinter : Printer will deconstruct that tree back into text file
So far so good, but I came across nasty problem - The connection between tree nodes is estabilished through std::vector<Node *> and I am not sure how to determine what child class is being processed.
My demo code:
class Node
{
public:
Node()
{
}
~Node()
{
for (auto it : Leaf)
delete it;
}
Node &Add(Node *leaf)
{
Leaf.push_back(leaf);
return *this;
}
std::vector<Node *> Leaf;
};
class NodeA : public Node
{
public:
NodeA() : Node()
{
}
};
class Printer
{
public:
Printer() = default;
std::string Print(Node &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<n>";
for (; i < k; ++i)
res += Print(*(n.Leaf[i]));
res += "</n>";
return res;
}
std::string Print(NodeA &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<A>";
for (; i < k; ++i)
res += Print(*(n.Leaf[i]));
res += "</A>";
return res;
}
};
int main(int argc, const char *argv[])
{
NodeA tree;
tree.Add(new NodeA).Add(new NodeA);
Printer p;
std::cout << p.Print(tree) << std::endl;
return 0;
}
Desired result: <A><A></A><A></A></A>
Actual result: <A><n></n><n></n></A>
I pretty much understand what is the problem (vector stores Node pointers, not NodeChild pointers), but not that sure how to overcome that. dynamic_cast seems to be not-the-solution-at-all.
So finally question - is there cure for me or am I longing for the wrong design altogether?
You used type erasure wrongly. Your nodes accessed by Node* , so *(n.Leaf[i]) expression returns type Node, not NodeA.
What you do resembles visitor pattern, to recognize which class is which you have to use a virtual method in Node class and override it in NodeA, calling it with dispatcher as argument (classic visitor) or calling it from dispatcher you can recognize which instance is which.
In first case node would call the Print method and pass it *this.
This is minimal rework of your code, but I think, it needs honing\optimizing. Depends on what your actual task is, vistor might be a little too excessive.
#include <string>
#include <iostream>
#include <vector>
class Node;
class NodeA;
class AbstractPrinter
{
public:
virtual std::string Print(Node &n) =0;
virtual std::string Print(NodeA &n) =0;
};
class Node
{
public:
Node()
{
}
virtual ~Node()
{
for (auto it : Leaf)
delete it;
}
Node &Add(Node *leaf)
{
Leaf.push_back(leaf);
return *this;
}
virtual std::string Print(AbstractPrinter& p)
{
return p.Print(*this);
}
std::vector<Node *> Leaf;
};
class NodeA : public Node
{
public:
NodeA() : Node()
{
}
// if not override this, it would use Node
virtual std::string Print(AbstractPrinter& p) override
{
return p.Print(*this);
}
};
class Printer : public AbstractPrinter
{
public:
Printer() = default;
std::string Print(Node &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<n>";
for (; i < k; ++i)
res += n.Leaf[i]->Print(*this);
res += "</n>";
return res;
}
std::string Print(NodeA &n)
{
int i = 0, k = n.Leaf.size();
std::string res = "<A>";
for (; i < k; ++i)
res += n.Leaf[i]->Print(*this);
res += "</A>";
return res;
}
};
int main(int argc, const char *argv[])
{
NodeA tree;
tree.Add(new NodeA).Add(new NodeA);
Printer p;
std::cout << tree.Print(p) << std::endl;
return 0;
}
I have a class that contains a tree structure implemented by a vector< vector< Node > > where Node contains a bunch of attributes exposed via getters/setters.
class Tree
{
vector< vector< Node > > mGrid;
printTree(std::ostream& output = std::cout);
};
class Node
{
double property1 { return mProp1; }
double property2 { return mProp2; }
};
printTree() is currently hardwired to use property tstep:
void Tree::printTree( ostream& output )
{
...
for (unsigned t = 0; t < mGrid.size(); ++t)
{
toPrint = "";
for (unsigned state = 0; state < mGrid[t].size(); ++state)
{
toPrint += to_string_with_precision( mGrid[t][state].tstep(), 1 );
...
Is there some slick / convenient / object-oriented way of generalizing this function so that it can print out any of Node's properties (rather than only spitting out the hardwired tstep() property or essentially doing the same thing via if/then statements).
I've done things like this in C using function pointers, but this is C++ and the C++ FAQ says not to mess with pointers to member functions.
You might want template function:
class Tree
{
vector< vector< Node > > mGrid;
public:
template <typename F>
void ForEachNode(F&& f) {
int i = 0;
for (auto& v : mGrid) {
int j = 0;
for (auto& node : v) {
f(node, i, j);
++j;
}
++i;
}
}
};
Then you may do
void printTreeProp1(Tree& tree) {
tree.ForEachNode([](const Node& node, int i, int j) {
if (i != 0 && j == 0) {
std::cout << std::endl;
}
std::cout << node.property1() << " ";
});
}
1st op all you loops are ignoring the first element. vector is zero based and you are using ++t and ++state which increases the values on top of the loop. That means you are never accessing the 0th element (mGrid[0] and mGrid[t][0]).2nd, you did noy include the definition of tstep(), so we don't know what you are getting back. Assuming you want to print each dimension of your 2 dimension array, I think you have to break it to peaces. Something like this:
class Node
{
protected:
double mProp1;
double mProp2;
public:
double GetProp1(void) {return mProp1;}
double GetProp2(void) {return mProp2;}
String tStep(void) {return L"";} // add your code here
};
class NodeRow : public std::vector<Node>
{
public:
void Print(std::ostream& output)
{
iterator i;
String tStr;
for(i = begin(); i != end(); i++)
tStr += /*to_string_with_precision(*/i->tStep()/*, 1)*/;
output << tStr.c_str() << L"\r\n";
}
};
class Node2D : public std::vector<NodeRow>
{
public:
void Print(std::ostream& output = std::cout)
{
iterator i;
for(i = begin(); i != end(); i++)
i->Print(output);
}
};
Ignoring a lot of detail:
Suppose i have an abstract Card class containing the function:
virtual int getType()=0;
derived by the also abstract GreenCard in which there is a
virtual int getType()=0;
as well.
Then GreenCard is derived by non-abstract Follower and Item where the pure virtual is defined:
int getType(){ return 1;}
in the Follower class and
int getType(){ return 2;}
in the Item class.
Later i create (and fill) a list of GreenCard pointers
list<GreenCard*>* hand;
...i want to print the hand cards (depending on their types) in a loop:
list<GreenCard *>::iterator it;
for(it=hand->begin() ; it!=hand->end() ; ++i){
tp.getCorrectType(*it);
...
}
and in this function i get the SegFault in the first line!
void getCorrectType(GreenCard* card)
{
/*SF here->*/ if(card->getType()==2){
...
}
}
i am sure that the "card" is properly created and initialized because right in the previous line i write in the gdb: p *card
...and i can see all of its fields (Card, GreenCard and Item related ones-yes it is an 'item') beeing correct!
Edit: ok then heres some more code:
class Player{
list<GreenCard*>* fateDeck;
list<GreenCard*>* hand;
static const int START_HAND = 4;
Player(){
fateDeck = new list<GreenCard*> ();
hand = new list<GreenCard*>();
}
void initialize(){
DeckBuilder db;
*fateDeck = *(db.createFateDeck() );
db.deckShuffler(fateDeck);
initializeHand();
}
void initializeHand(){
for(int counter=0 ; counter<START_HAND ; counter++){
drawFateCard();
}
void drawFateCard(){
hand->push_front(fateDeck->front());
fateDeck->pop_front();
cout<<'\n'<<"Drawing from fate deck..."<<'\n'<<endl;
}
void Player::printHand(){
TypeConverter tp;
list<GreenCard *>::iterator it;
cout<<"You have " << hand->size()<<" fate cards in hand"<<'\n'
<<"They are the following:"<<endl;
for(it=hand->begin() ; it!=hand->end() ; ++it){
tp.getCorrectType(*it);
// printing depending on type
}
}
void startingPhase(){
printHand();
}
}
class DeckBuilder
{
private:
list<GreenCard*>* green;
public:
DeckBuilder();
list<GreenCard *>* createFateDeck();
void deckShuffler(list<GreenCard*>* green);
};
DeckBuilder :: DeckBuilder()
{
green = new list<GreenCard*>();
srand ( unsigned ( time (NULL) ) );
}
list<GreenCard *>* DeckBuilder :: createFateDeck()
{
int i;
for(i=0;i<40;i++) green->push_back(new Follower());
return green;
}
void DeckBuilder :: deckShuffler(list<GreenCard*>* green)
{
vector<GreenCard *> vect;
list<GreenCard*> ::iterator it;
for(it = green->begin();it!=green->end();it++)
vect.push_back((*it));
random_shuffle ( vect.begin(), vect.end() );
green->clear();
vector<GreenCard*>:: iterator it2;
for(it2 = vect.begin();it2!=vect.end();it2++)
green->push_back((*it2));
}
and eventually in main()
Player pl();
pl.initialize();
pl.startingPhase;
and segfaults in printHand();
I've pieced together the information you've given me. This compiles and runs without segmentation faults (using Visual Studio 2013):
#include "stdafx.h"
#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
#include <ctime>
using namespace std;
class Card
{
public:
virtual int getType() = 0;
};
class GreenCard : public Card
{
public:
virtual int getType() = 0;
};
class Follower : public GreenCard
{
public:
int getType(){ return 1; }
};
class Item : public GreenCard
{
public:
int getType(){ return 2; }
};
class TypeConverter
{
public:
void getCorrectType(GreenCard* card)
{
if (card->getType() == 1)
std::cout << "Follower" << std::endl;
if (card->getType() == 2){
std::cout << "Item" << std::endl;
}
}
};
class DeckBuilder
{
private:
list<GreenCard*>* green;
public:
DeckBuilder();
list<GreenCard *>* createFateDeck();
void deckShuffler(list<GreenCard*>* green);
};
DeckBuilder::DeckBuilder()
{
green = new list<GreenCard*>();
srand(unsigned(time(NULL)));
}
list<GreenCard *>* DeckBuilder::createFateDeck()
{
int i;
for (i = 0; i < 40; i++) green->push_back(new Follower());
return green;
}
void DeckBuilder::deckShuffler(list<GreenCard*>* green)
{
vector<GreenCard *> vect;
list<GreenCard*> ::iterator it;
for (it = green->begin(); it != green->end(); it++)
vect.push_back((*it));
random_shuffle(vect.begin(), vect.end());
green->clear();
vector<GreenCard*>::iterator it2;
for (it2 = vect.begin(); it2 != vect.end(); it2++)
green->push_back((*it2));
}
class Player{
public:
list<GreenCard*>* fateDeck;
list<GreenCard*>* hand;
static const int START_HAND = 4;
Player(){
fateDeck = new list<GreenCard*>();
hand = new list<GreenCard*>();
}
void initialize(){
DeckBuilder db;
*fateDeck = *(db.createFateDeck());
db.deckShuffler(fateDeck);
initializeHand();
}
void initializeHand(){
for (int counter = 0; counter < START_HAND; counter++){
drawFateCard();
}
}
void drawFateCard(){
hand->push_front(fateDeck->front());
fateDeck->pop_front();
cout << '\n' << "Drawing from fate deck..." << '\n' << endl;
}
void Player::printHand(){
TypeConverter tp;
list<GreenCard *>::iterator it;
cout << "You have " << hand->size() << " fate cards in hand" << '\n'
<< "They are the following:" << endl;
for (it = hand->begin(); it != hand->end(); ++it){
tp.getCorrectType(*it);
// printing depending on type
}
}
void startingPhase(){
printHand();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Player pl;
pl.initialize();
pl.startingPhase();
return 0;
}
Please provide a small, stand-alone example that demonstrates the error.
I've a question to ask.
So, I have a structure call Node as shown below:
struct Node
{
int xKoor, yKoor;
Node *parent;
char nodeId;
float G;
float H;
float F;
Node(int x, int y, int id, Node * par)
{
xKoor = x;
yKoor = y;
nodeId = id;
parent = 0;
}
Node(int x, int y, char id)
{
xKoor = x;
yKoor = y;
nodeId = id;
}
};
And I have list that contains elements of this structure:
list<Node*> OPEN;
This list's size varies in time.
What I need to do is to find the Node object which has the minimum F value, then pop out that object from the list.
So, I tried to write a function as shown below:
void enKucukFliNodeBul(list<Node*> OPEN)
{
list<Node*>::iterator it = OPEN.begin();
for(it = OPEN.begin(); it != OPEN.end(); it++)
{
if(it._Ptr->_Myval->F < it._Ptr->_Next->_Myval->F)
{
}
}
}
But I'm stuck. I'm new to STL. How can I solve this?
My best regards...
You can use std::min_element with a suitable comparison function for this.
bool nodeComp(const Node* lhs, const Node* rhs) {
return lhs->F < rhs->F;
}
#include <algorithm> // for std::min_element
list<Node*>::iterator it = std::min_element(OPEN.begin(), OPEN.end(), nodeComp);
This assumes that list<Node*> is std::list<Node*>, in which case you should be aware that std::list itself is a linked list.
Other useful operations, based on your comments:
Remove a minimum value node from the list and delete it:
OPEN.erase(it);
delete *it; //
You may need to perform other operations, if your nodes depend on each other.
Sort the list:
OPEN.sort(nodeComp);
use std::min_element algirithm and overload Compare function
bool compareF(Node *lhs, Node *rhs)
{
return lhs->F < rhs->F;
}
if you are using C++03:
std::<Node*>::itertor ter = std::min_element(OPEN.begin(),OPEN.end(), compareF);
if you are using C++11:
auto iter = std::min_element(OPEN.begin(),OPEN.end(), compareF);
To sort the list, you can call OPEN.sort(compareF); to sort your list with compareF function
Try adding this:
bool compare_node_F(Node* n1, Node* n2)
{
return n1-> F< n2-> F;
}
#include <list>
#include <algorithm>
#include <cstdlib>
#include <iostream>
int main()
{
std::list<Node*> nodes;
for(int i= 100; i--;)
{
Node* n= new Node(42, 42, 42);
n-> F= i;
nodes.push_back(n);
}
std::list<Node*>::iterator min_element_iter= std::min_element(nodes.begin(), nodes.end(), compare_node_F);
std::cout<< "Min F: "<< (*min_element_iter)-> F<< '\n';
for(std::list<Node*>::iterator d= nodes.begin(); d!= nodes.end(); ++ d)
delete *d;
}