I am writing a c++ program to code for dijkstra's algorithm. Here is the code.
#include <iostream>
#include <vector>
#include <map>
using namespace std;
class vertex;
class node
{
public:
int value;
//bool exp=false;
char c;
};
class edge
{
public:
vertex* head;
vertex* tail;
int length;
edge(vertex*h,vertex* t, int l)
{
head=h;
tail=t;
length=l;
}
};
class vertex:public node
{
public:
vector<edge*> a;
vertex& operator|(vertex &p)
{
int l;
cout<<"Give the length of edge "<<this->c<<p.c<<endl;
cin>>l;
edge q(&p,this,l);
a.push_back(&q);
}
vertex(char a)
{
c=a;
}
};
int main()
{
vertex e('e');
vertex d('d');
vertex b('b');
vertex c('c');
vertex a('a');
vertex s('s');
s.value=1;
a.value=2;
b.value=3;
c.value=4;
d.value=5;
e.value=6;
s|a;
s|b;
a|c;
b|c;
b|d;
c|d;
c|e;
d|e;
cout<<"4";
map <char ,int >A;
vector<edge*>::iterator minin;
vector<edge*>::iterator j;
int min=0;
vector<vertex*> X;
X.push_back(&s);
A['s']=0;
vector<vertex*>::iterator i=X.begin();
for(; i<X.end(); i++)
{
cout<<"1";
j=((*i)->a).begin();
for(; j<((*i)->a).end(); j++)
{
cout<<"2";
if((*j)->length+A[((*j)->tail)->c]>min)
{
cout<<"3";
minin=j;
min=(*j)->length+A[((*j)->tail)->c];
}
}
}
X.push_back((*minin)->head);
A[((*minin)->tail)->c]=min;
cout<<((*minin)->head)->value;
}
The program returns a segmentation fault. I have used various cout statements to check where the fault occured but nothing is printed in console. However, I am able to input the edge length in the console but after giving the input it directly gives segmentation fault.
In
a.push_back(&q);
you are storing the address of a local object, which will cease to exist once the function terminates.
Why are you creating a class to keep your vertices/nodes?. I think you should use plain integers from 0 to N - 1 to avoid get things more complicated. If vertices are identified by a string or something else, you could use a hash/map data structure to transform the keys to an integer. That will help you to avoid moving complex vertex structures and using pointers.
The Edge class seems fine because the Dijkstra's algorithms needs all that data to work (start, end vertices, and the weight/cost of the path).
Having said that, the algorithm could be implemented using a binary heap data structure to prioritize the edge selection. You could also use a priority queue (http://en.cppreference.com/w/cpp/container/priority_queue) if you don't want to implement a binary heap.
Finally, I would use a Edge vector to iterate over the adjacent vertices of every vertex.
Related
Basically I am creating a mesh composed of nodes and springs and I keep receiving the segmentation fault (core dumped) error when trying to access an element of the nodes vector defined in the Mesh class in main().
When I run a test output within the Mesh class' constructor, I can access the node member just fine. I'm sure it's a memory problem but could anyone explain why this is happening?
Node class:
class Node
{
public:
/// (Non-)magic number indicating that the coordinate has not
/// been classified as pinned or free yet
static int Not_classified_yet;
/// (Non-)magic number indicating that the coordinate is pinned
static int Is_pinned;
/// Constructor: Pass the spatial dimension
Node(const unsigned& dim)
{
// Resize
X.resize(dim,0.0);
Eqn_number.resize(dim,Not_classified_yet);
}
/// Function to add a spring to the node
void add_spring_pt(Spring* spring_pt)
{
Spring_pt.push_back(spring_pt);
}
/// How many springs are attached to this node?
unsigned nspring()
{
return Spring_pt.size();
}
/// Access function to the ith spring connected to the node
Spring*& spring_pt(const unsigned& i)
{
return Spring_pt[i];
}
/// Access function to the position vector of the node
vector<double>& get_vector()
{
return X;
}
/// Access function to the coordinates of the node
double& x(int i)
{
return X[i];
}
/// Access function to the equation number for each coordinate
/// Can be negative if node is pinned in that direction.
int& eqn_number(const unsigned& i)
{
return Eqn_number[i];
}
/// Pin the i-th coordinate
void pin(const unsigned& i)
{
Eqn_number[i]=Is_pinned;
}
/// Is the i-th coordinate pinned?
bool is_pinned(const unsigned& i)
{
return (Eqn_number[i]==Is_pinned);
}
private:
/// Pointers to the springs attatched to the node.
vector<Spring*> Spring_pt;
/// Coordinates of the node
vector<double> X;
/// Vector containing equation indices for each coordinate direction.
/// Can be negative if node is pinned in that direction.
vector<int> Eqn_number;
};
Mesh class:
class Mesh
{
public:
/// constructor (nX contains number of nodes in each direction)
Mesh(const vector<unsigned> nX)
{
/// Function "num_nodes" defined in "myFunctions.cpp" to find the
/// total number of nodes.
unsigned nNodes = num_nodes(nX);
/// Check the dimension of the mesh and and construct a vector
/// of the nodes.
unsigned dim = nX.size();
vector<Node> nodes(nNodes,dim);
//std::cout<< nodes[1].x(0)<<std::endl;
/// Function "num_springs" defined in "myFunctions.cpp" to find the
/// total number of springs.
unsigned nsprings = num_springs(nX);
/// Vector to hold the springs.
vector<Spring> springs(nsprings);
/// Function to assign coordinates to all the nodes.
assign_coordinates(nodes,nX);
}
/// Access function to the ith node of the mesh.
Node& node(const unsigned& i)
{
return nodes[i];
}
/// Function declaration for assigning coordinates to nodes
void assign_coordinates(std::vector<Node>& nodes, std::vector<unsigned> nX);
/// Access function to the ith spring of the mesh.
Spring& spring(const unsigned& i)
{
return springs[i];
}
private:
/// Declare vectors to hold the nodes and springs.
vector<Node> nodes;
vector<Spring> springs;
};
And what I am trying to output from the main():
int main()
{
// create a mesh
// spatial dimensions
unsigned nx = 3;
unsigned ny = 3;
unsigned nz = 3;
vector<unsigned> nX(2);
nX[0] = nx;
nX[1] = ny;
//nX[2] = nz;
Mesh m(nX);
// segmentation fault (core dumped)
std::cout << m.node(6).eqn_number(1) << std::endl;
};
Thanks in advance for any help.
The problem (a problem?) is in Mesh constructor when you define
vector<Node> nodes(nNodes,dim);
I suppose that your intention was initialize the nodes member of the Mesh class; what you get is a nodes variable that is local to the Mesh constructor.
The nodes member of Mesh is initialized with the implicit default constructor, so the vectors in the Nodes (Spring_pt, X and Eqn_number) are initialized with the default std::vector constructor so with zero size.
When you call
m.node(6).eqn_number(1)
with node(6) you call the 7th element of a std::vector of size zero.
Same problem with
std::vector<Spring> springs(nsprings);
in the Mesh constructor: you declare and initialize a springs variable local in the constructor where your intention (I suppose) was initialize the springs member of Mesh.
If I understand correctly your intentions, you should be able to solve the problem writing your constructor as follows
Mesh (const std::vector<unsigned> nX)
: nodes(num_nodes(nX), nX.size()), springs(num_springs(nX))
{ assign_coordinates(nodes,nX); }
At a quick glance it looks like you initialized your mesh with 2 nodes and then went asking for the 7th (indexed starting at 0).
A quick way to check for this is to change nodes[i] to nodes.at(i) which will enable out-of-bounds checking for vector element accesses.
To represent a Graph in adjacency-list style, I'm using a vector containing pointers to a list of adjacent.
class Graph
{
public:
Graph(int V)
{
vector<list<int> *> vertices(V);
}
// Member functions for Graph class
void addEdge();
void print();
void type(string);
private:
vector<list<int> *> vertices;
};
Getting the number of vertices from the user in main function-> passing it to the constructor, it all works, meaning the vector is being initialized of the desired size! But right after the program comes back from the header file to the main function, Things change! as in tracing the value of vertices: the size is somehow being reset somewhere that I don' know of!!!
int size;
cout << "Enter the number of vertices in the Graph: ";
cin >> size;
Graph g(size);
Immona need help with this, what could possibly go wrong?!
You're creating a temporary vector (local variable) in your constructor :
Graph(int V)
{
vector<list<int> *> vertices(V);
}
You need to initialize your member variable instead :
Graph(int V) : vertices(V) {}
Also, I would suggest using std::unique_ptr<list<int>> instead of raw pointers if you really need to use pointers, else simply store plain std::list<int>.
The program seg faults once it reaches this line of code (the code is in Graph.cpp in the function set_array.)
adjList[adjList.size()].push_back(Edge(vertex, 0));
Basically, I want this line to be called every time i need to make the vector longer to fit more linked lists, as the structure is an vector of linked lists. Here is the .h file that declares the vector of linked lists and its contents. Every node will contain a vertex and a weight. (The node class is known as class Edge.)
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
//class MinPriority;
#include <iostream>
#include <string>
#include <vector>
#include <list>
using namespace std;
class Graph
{
public:
Graph();
~Graph();
void set_Edge(string targetVertex, string vertex, int weight);
void set_array(string vertex);
void print_Test();
friend class MinPriority;
private:
class Edge
{
public:
Edge(string vertex, int weight)
{m_vertex = vertex; m_weight = weight;}
~Edge(){}
string m_vertex;
int m_weight;
};
vector< list<Edge> > adjList; //declaration of the array of linked lists
};
#endif // GRAPH_H_INCLUDED
here is what I want adjList[adjList.size()].push_back(Edge(vertex, 0)); to do; basically every time I want to insert a new vertex into the graph, I will call this. It seg faults as soon as I try to put the first item in the tree. Ill call to insert 'A' with a weight of '0' and it will immediately seg fault. By the way, I am trying to make an adjacency list where i use adjList[adjList.size()].push_back(Edge(vertex, 0)); to add a new (unused) vertex into the graph. Lets pretend this is passed into the function...
A B C D
After doing this, the vector's length should increase by 4. But of course it instead seg faults at that line (it tells me in GDB). I'm very new to using wierd data structures like this so any help would be very appreciated.
Try
adjList[adjList.size()-1]
The arrays are indexed 0..(size-1).
For instance, the indices of a 4 element array are 0, 1, 2 and 3.
If there is a possibility that the array is empty, you can add logic to prevent any access at all --
if (adjList[adjList.size() > 0) ...
Try to cast your array index :
adjList[int(adjList.size())]
Or try with 0 ?
EDIT : It seems you have to manually enter the lists before pushing Edge elements in it.
// Creation of independant lists
list<Edge> Eg, Ec;
Edge h("AB", 0);
Edge f("CD", 0);
adjList.push_back(Eg);
adjList[adjList.size()-1].push_back(h);
adjList.push_back(Ec);
adjList[adjList.size()-1].push_back(f);
// Return 2
cout << adjList.size();
I haven't found another way yet. But i'm no c++ expert.
The following code is the the beginning of an adjacency list representation of a graph.
In the buildGraph, which is immediately called by main, two vertices are created, then an edge is created between them. But then asking for the size of the edgelist of a vertex should return 1, not 0. I have tried putting couts in various places, and I'm just not able to figure out what the problem is, but I suspect it's due to a misunderstanding of pointers in some way. Thank you for your help!
#include "MinCut.h"
#include <iostream>
#include <list>
void buildGraph(undirected_graph *);
class vertex;
struct edge
{
vertex * start;
vertex * end;
};
class vertex
{
int vertexNumber;
std::list<edge> edges;
public:
int getVertexNumber(){return vertexNumber;}
std::list<edge> getEdges(){return edges;}
vertex(int n){vertexNumber=n;}
};
class undirected_graph
{
private:
std::list<vertex> graph;
public:
void addVertex(vertex v){graph.push_back(v);}
void createEdge(vertex * v1, vertex * v2);
};
void undirected_graph::createEdge(vertex * v1, vertex * v2)
{
std::list<edge> e1 = v1->getEdges();
std::list<edge> e2 = v2->getEdges();
edge e;
e.start=v1;
e.end=v2;
e1.push_back(e);
e2.push_back(e);
}
int main()
{
undirected_graph myGraph;
buildGraph(&myGraph);
return 0;
}
void buildGraph(undirected_graph * g)
{
vertex v1(1);
vertex v2(2);
g->addVertex(v1);
g->addVertex(v2);
g->createEdge(&v1,&v2);
std::list<edge> e = v1.getEdges();
std::cout<< "? " << e.size();
}
In createEdge() you have this:
e.start=v1;
e.start=v2;
Should it instead be
e.start=v1;
e.end=v2;
EDIT: Your problem is in createEdge, e1 and e2 are just copies, so changes don't affect the actual vertex objects.
Here's my solution, seems to be working:
Add a function to vertex like so:
void addEdge(edge &e){edges.push_back(e);}
Then in createEdge():
edge e;
e.start=v1;
e.end=v2;
v1->addEdge(e);
v2->addEdge(e);
In addition to #PatLillis's answer, I think you're also going to run into problems here:
vertex v1(1);
vertex v2(2);
g->addVertex(v1);
g->addVertex(v2);
g->createEdge(&v1,&v2);
The pointers &v1 and &v2 refer to v1 and v2 in your main function. However:
Since you're passing v1 and v2 by value to addVertex, you're going to get copies of those vertices in addVertex. That means your pointers in main will be pointing one place, and the copies will be somewhere else.
Since you're storing your vertices by value in a std::list, you'll have the same problem again. The list will hold copies of the copies in addVertex, and your pointers will still be pointing to the originals in main.
One way to fix this is to deal with vertex* in e.g. addVertex and in your std::list. Alternatively, if you want your graph to "own" the vertices (as opposed to them having potentially separate lifetimes from the graph) you could switch to std::unique_ptr<vertex>.
I have struct like this:
struct element{
char ulica[10];
vector<int> dane[3];
int wolne;
int w;
element *lewy, *prawy, *ojciec;
};
And I'm implementing kind of AVL tree. When key's are the same i need to put some int values to dane (dane[0], dane[1], dane[2] describe 3 different value) so I use
tmp2->dane[0].push_back(number)
EDIT. Here is code where I'm adding a values to this vector, it's half of the function because secod half is about rotations in AVL.
void wstaw_wezel(){
element *tmp2; //tmp2 bedzie ojcem nowo wstawionego elementu
tmp2=korzen;
while(tmp2!=NULL){
if(strcmp(tmp2->ulica, tmp->ulica)<0){
if(tmp2->prawy!=NULL){
tmp2=tmp2->prawy;
}
else{
tmp->ojciec=tmp2;
tmp2->prawy=tmp;
cout<<"Wstawiam pod prawy "<<tmp2->ulica<<endl;
if(tmp2->w!=0) tmp2->w=0;
else tmp2->w=-1;
break;
}
}
else if(strcmp(tmp2->ulica, tmp->ulica)>0){
if(tmp2->lewy!=NULL){
tmp2=tmp2->lewy;
}
else{
tmp->ojciec=tmp2;
tmp2->lewy=tmp;
if(tmp2->w!=0) tmp2->w=0;
else tmp2->w=1;
cout<<"Wstawiam pod lewy "<<tmp2->ulica<<endl;
break;
}
}
else{
cout<<"2 bloki na tej samej ulicy"<<endl;
for(int i=0; i<tmp2->dane[0].size(); i++) cout<<tmp2->ulica<<" "<<tmp2->dane[0][i]<<endl;
tmp2->numery.push_back(tmp->numery[0]);
tmp2->dane[0].push_back(tmp->dane[0][0]);
for(int i=0; i<tmp2->dane[0].size(); i++) cout<<tmp2->ulica<<" "<<tmp2->dane[0][i]<<endl;
tmp2->dane[1].push_back(tmp->dane[1][0]);
tmp2->dane[2].push_back(tmp->dane[2][0]);
tmp2->wolne+=tmp->dane[2][0];
break;
}
}
if(tmp->ojciec==NULL){
korzen=tmp;
return;
}
where tmp2 is a pointer to this struct (I checked adrres where it points and every time it's the same adrres).
Where is problem? If I add new value to vector it is until the loop where i do it ends. Finally instead having fe. 4 values in vector i have one, the last added value. Vector don't add new value to the end, just replacing it.
You declare the initial size of a std::vector in its constructor, so one way you can accomplish this is:
struct element
{
char ulica[10];
std::vector<int> dane;
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element() : dane(3) {}
};
If you don't include the constructor, the initial size of the vector will be 0. In any event, to add an element to the back, just use tmp2->dane.push_back(number); This will add the value in number to the back of the vector tmp2->dane which may result in a change in the amount of allocated memory for the vector instance.
UPDATE: Based on the comment from the OP that he needs three vectors try this:
struct element
{
char ulica[10];
std::vector<std::vector<int> > dane;
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element() : dane(3) {}
};
To add elements to the vectors, simply use tmp2->dane[i].push_back(number) where i is the index of the vector to use, and number is the new number to add to the ith vector, which is the same convention you seem to be using in your code segment above.
Update 2: Based on additional information below, I think a redesign of your data structure is called for. You're mixing the meaning of the various components and by more clearly delineating the functions of the data element and the AVL data structure management, you will be able to more clearly distinguish between the two. So try this instead. Have a data structure specifically for the "value" portion of your tree nodes, as in:
struct house
{
int house_number;
int unique_value0;
int unique_value1;
house(int hn, int uv0, int uv2)
: house_number(hn),
unique_value0(uv0),
unique_value1(uv1) {}
};
template <typename VALUE> struct node
{
std::string key;
std::vector<VALUE> values;
int left, right;
node<VALUE> *leftNode, *rightNode, *parentNode;
};
From here, you create a root node:
node<house> *root;
When you want to add a house to a street, node<house> *s, all you need to do is
s->values.push_back(house(a, b, c));
Of course a better alternative is to use what C++ already has for this. That is, there is a structure in the standard library called std::multimap which does pretty much what you're trying to do. In this case, you can simple declare
std::multimap<std::string, house> myMap;
This probably won't use AVL balancing. It more likely will be a Red-Black Tree, but it's all done for you.
How do you alloc the struct element?, it seems that the vector<int> dane[3]; has been initialized successful, but its inner vector does not been initialised.
try to add a ctor method to the struct element?
struct element
{
char ulica[10];
vector<int> dane[3];
int wolne;
int w;
element *lewy, *prawy, *ojciec;
element()
{
dane[0] = vector<int>();
dane[1] = vector<int>();
dane[2] = vector<int>();
}
};