Segmentation Fault C++ - c++

The input is in the following format
5
1 2 9.0
1 3 12.0
2 4 18.0
2 3 6.0
2 5 20.0
3 5 15.0
0
1 5
The first number is the number of vertexes in the graph. Then next lines up to 0 are the edges of the graph. With the first and second numbers being the vertexes and the third being how far the edge is between them. Trying to read in the data and store the edges into there locations in the List adjacency for that vertex. This example would make a graph with five vertexes with edges from 1 to 2&3. 2 to 4&3&1 etc.
I am getting a Segmentation fault after entering four numbers. The fault is happening on line myGraph.vertexInfo[p1].adjacency -> vertex=p2; where is starts trying to store the information. Why am I getting this fault?
#include <cstdio>
using namespace std;
struct ListCell
{
ListCell* next;
int vertex;
double weight;
ListCell(int v, double w, ListCell* nxt)
{
vertex = v;
weight = w;
next = nxt;
}
};
typedef ListCell* List;
struct Vertex
{
bool signaled;
long distance;
List adjacency;
};
struct Graph
{
int numVertices;
Vertex* vertexInfo;
Graph(int n)
{
numVertices = n;
vertexInfo = new Vertex[n+1];
for(int i = 1; i <= n; i++)
{
vertexInfo[i].signaled = false;
}
}
};
//==============================================================
// readIn
//==============================================================
//
//==============================================================
void readIn()
{
int g;
int p1;
int p2;
float edge;
scanf("%i ", &g);
Graph myGraph(g);
scanf("%i", &p1);
while(p1 != 0)
{
scanf("%i", &p2);
scanf("%f", &edge);
myGraph.vertexInfo[p1].adjacency -> vertex=p2;
myGraph.vertexInfo[p2].adjacency -> vertex=p1;
myGraph.vertexInfo[p1].adjacency -> weight=edge;
myGraph.vertexInfo[p2].adjacency -> weight=edge;
scanf("%i", &p1);
}
}
//==============================================================
// main
//==============================================================
int main(int argc, char** argv)
{
readIn();
return 0;
}

You are not following some of the fundamental principles of object construction and intialization for Vertex.
When you construct an instance of Vertex, there is nothing predictable about the values of the member data. I would suggest adding a default constructor that initializes the member data to something sane.
struct Vertex
{
Vertex() : signaled(false), distance(0), adjacency(NULL) {}
bool signaled;
long distance;
List adjacency;
};
Once you do that, the constructor for Graph can be simplified to:
Graph(int n) : numVertices(n)
{
vertexInfo = new Vertex[n+1];
}

Let's look at what adjacency is:
struct Vertex
{
bool signaled;
long distance;
List adjacency;
};
And now let's look at what List is:
typedef ListCell* List;
So, adjacency is actually a pointer to a ListCell. That's fine, we can work with that. But before we can, we must make sure that adjacency actually points to something. The question then becomes what does adjacency point to in your code?
The answer is: who knows? You never make it point to anything, so it's pointing somewhere randomly. And what happens when you try to write to some random area of memory? Well, if you're lucky, you crash.
So, how do you solve this problem? Simple: initialize and manipulate adjacency correctly. You may wish to look into dynamic memory allocation in C++ and the standard library which provides a rather nifty and working implementation of a linked list.
Sidenote: you seem to treat adjacency as a linked list. However, you ought to note that adjacency is a pointer to a node in a linked list. Again, now would a great time to learn about std::list.

The adjacency pointer is uninitialized, so you run into problems when dereferencing it.

You have to initialize your adjacency member:
Graph(int n)
{
numVertices = n;
vertexInfo = new Vertex[n+1];
for(int i = 1; i <= n; i++)
{
vertexInfo[i].signaled = false;
vertexInfo[i].adjacency = new ListCell(i, 0.0, 0);
}
}

Related

segmentation fault with big array size [duplicate]

so I've been running into a problem where somehow my code is causing segmentation faults before any of my main actually runs. I've never had this happen before and I hardly have a quarter's worth of coding experience so I'm not sure if there's something I'm doing wrong. Everything compiles, at least on my computer, but upon running it my main is never reached.
Context: I'm trying to connect Vertices and Edges in an adjacency matrix and then use Prim's algorithm to build an MST, but that's for later. I built a header file, which originally contained only typdef calls for the structures and the functions. However, I switched the structure definitions to the header file because I was getting memory errors; hence why I think there's an issue with the structs.
graph.h:
//Leland Wong 00000897031
//graph header file
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#ifndef GRAPH_H
#define GRAPH_H
typedef struct vertex
{
double longitude;
double latitude;
char city[30];
int index;
int visited; //0: not visited, 1: visited, 2: visited
struct edge* nexte;
struct vertex* nextv;
double projected;
}VERTEX;
typedef struct edge
{
struct vertex* start;
struct vertex* destination;
double distance;
struct edge* nexte;
}EDGE;
typedef struct graph
{
struct vertex* list[756];
struct edge* matrix[756][756];
}GRAPH;
/*
typedef struct vertex VERTEX;
typedef struct edge EDGE;
typedef struct graph GRAPH;
*/
double findDistance(VERTEX* v1, VERTEX* v2); //compute the distance between two locations
EDGE* connect(VERTEX* v1, VERTEX* v2); //connects two vertices and returns the connecting EDGE
GRAPH primMatrix(GRAPH *g); //connects all vertices using Prim's Algorithm in an adjacency matrix
//void lPrimConnect(VERTEX v); //connects all vertices using Prim's Algorithm in an adjacency list
EDGE* findSmallestEdge(VERTEX v, GRAPH *g); //finds the smallest EDGE connected to v
#endif
graph.c: contains the implementations of all my functions
//functions
//computes the distance between v1 and v2
double findDistance(VERTEX* v1, VERTEX* v2)
{
printf("findDistance");
double long1 = v1->longitude;
double long2 = v2->longitude;
double lat1 = v1->latitude;
double lat2 = v2->latitude;
double distance = 0;
if(long1 < 0)
long1 += 360;
if(long2 < 0)
long2 += 360;
distance = powf((long1-long2), 2) + powf((lat1 - lat2), 2);
distance = sqrt(distance);
return distance;
}
//creates and returns an edge that connects v1 and v2
EDGE* connect(VERTEX* v1, VERTEX* v2)
{
printf("connect");
EDGE *new;
new->start = v1;
new->destination = v2;
new->distance = findDistance(v1, v2);
return new;
}
//finds smallest edge connected to v in GRAPH g
EDGE* findSmallestEdge(VERTEX v, GRAPH *g)
{
printf("findSmallestEdge");
EDGE *tempe;
int i, index;
index = v.index;
//set tempe equal to the first edge connected to v
tempe = g->matrix[index][0];
//find smallest edge connected to v
for(i = 0; i < 756; i++)
{
if(g->matrix[index][i] -> distance < tempe->distance && g->list[index]->visited == 0)
{
tempe = g->matrix[index][i];
}
}
return tempe;
}
//creates an MST out of GRAPH g using Prim's algorithm
GRAPH primMatrix(GRAPH *g)
{
printf("primMatrix");
GRAPH new; // = malloc(sizeof(GRAPH));
EDGE *smallest;
EDGE *tempe;
int i, x;
i = 1;
x = 0;
new.list[0] = g->list[0]; //add root node to MST
g->list[0]->visited = 2;
smallest = findSmallestEdge(*new.list[0], g);
new.matrix[0][smallest->destination->index] = smallest;
//MST will contain all 756 nodes, so run this 755 times to ensure all nodes are reached
while(i < 756)
{
x = 0;
smallest = findSmallestEdge(*new.list[i], g);
//i = number of vertices already reached
while(x < i)
{
tempe = findSmallestEdge(*new.list[x], g);
if(tempe -> distance < smallest -> distance)
{
smallest = tempe;
}
x++;
}
new.list[i] = smallest -> destination;
smallest -> destination -> visited = 2;
new.matrix[smallest->start->index][smallest->destination->index] = smallest;
i++;
}
return new;
}
graphmatrixmain.c: my main function which builds the graphs
#include "graph.h"
int main(int argc, char* argv[])
{
FILE *fp;
static GRAPH g;
char buffer[200];
int i, j;
char city[30];
char *long1;
char *lat1;
if(argc == 1)
{
printf("could not open file\n");
return 0;
}
else
fp = fopen(argv[1], "r");
//read in line of data from txt file, build a new vertex, and insert into list
while(fgets(buffer, 200, fp) != NULL)
{
VERTEX *new = malloc(sizeof(VERTEX));
printf("%s", buffer);
sscanf(buffer, "%s %s %s", city, long1, lat1);
//sscanf(buffer, "%[^\t]\t%[^\t]\t%s", city, long1, lat1);
printf("scanned in data\n");
new->longitude = atof(long1);
new->latitude = atof(lat1);
new->index = i;
g.list[i] = new;
printf("%s: (%lf, %lf)", new->city, new->longitude, new->latitude);
i++;
}
//create EDGE and make connects between every VERTEX in list
for(i = 0; i < 756; i++)
{
for(j = 0; j < 756; j++)
{
g.matrix[i][j] = connect(g.list[i], g.list[j]);
if(j == 0)
{
g.list[i]->nexte = g.matrix[i][j];
}
}
}
return 0;
}
In case its necessary, this is the file i'm reading in from: cities.txt
it contains 756 entries total but as far as the code is concerned size shouldn't be relevant
Shanghai 121.47 31.23
Bombay 72.82 18.96
Karachi 67.01 24.86
Buenos Aires -58.37 -34.61
Delhi 77.21 28.67
Istanbul 29 41.1
Manila 120.97 14.62
Sao Paulo -46.63 -23.53
Moscow 37.62 55.75
I've been running into a problem where somehow my code is causing segmentation faults before any of my main actually runs.
Usually, this means that the data structures that your main tries to place in the automatic storage area overflow the stack. In your situation, it looks like the GRAPH is a suitable suspect to do just that: it has a 2D array with 571536 pointers, which could very well overflow the stack before your main gets a chance to start.
One solution to this problem would be moving the GRAPH into the static area: since you allocate it in the main, it's going to be only one instance of it anyway, so declaring it static should fix the problem:
static GRAPH g;
You might also want to allocate it in the dynamic area using malloc, but in this case it probably does not matter.
Your problem is not "before main" as you state, but in the first few lines of your program. You are not initializing fp, so it could go anywhere. You also have memory errors in your loop with new. You need to copy the value into newly allocated memory.
You cannot see the printfs in your code because the output is buffered and your code crashes before the buffer is flushed. If you put exit(0) just after your printf("error");, you'll see that it works.
I had faced "Segmentation fault occurs before main() execution begins" issue in my C++ code.
Let me try to explain what my issue was and how I could solve it.
A global/static class instance is present in code.
Its constructor is invoked before main() begins.
Inside constructor,in an error handling part, std::cerr is used to display error.
std:cerr was not initialized when constructor was executed.
Even though it says, if #include iostream is there before object is defined then std::cerr is initialized, it was not.
https://en.cppreference.com/w/cpp/io/cerr
If object of std::ios_base::Init is created before constructor, it ensures proper init and deinit of default c++ streams.
why std::cerr was not initialized,
In c++11 objects in iostream are init before other global objects.
But in c++03, it is unspecified.
Use std::ios_base::Init as a private member of class to ensure it is init before stream functions are executed.
Is std::cout guaranteed to be initialized?
One possible reason for segmentation fault before main is the program was mistakenly linked with -shared option. I wasted a lot of time trying to debug it.

degree of connection between 2 nodes in a social graph

I'm trying to find out the degree of connection between 2 entities in a social graph where
1 hop : 1st Degree
2 hop : 2nd Degree
3 hop : 3rd Degree
And so on.
The vertices are the entities and the edges are the friendship between the two entities. Given such a graph I want to analyse the graph and answer the query as to what is the type of connection between the entities.It can be disconnected graph.In case of no connection it'll return 0.
It takes the input as-
Number_of_vertices Number_of_Edges
Edge 1
Edge 2
(So on.)
Query
Output
The degree of connection
Example
Input
5 4
Abhs Krax // Edge 1
Harry Idrina // Edge 2
Harry Jigma // Edge 3
Harry Krax // Edge 4
Abhs Jigma // Query
Output
Degree : 3
I've used BFS to find out the depth between 2 nodes, but my program works only for degree 1. It fails to test the next subsequent member of the queue thus stuck at testing only the 1st member of the queue. What did I miss in my code? The problem is in Connection() function which I couldn't trace.
#include <iostream>
#include <list>
#include <string>
using namespace std;
class Vertex // Each vertex of the graph is represented by the object of the Vertex class
{
public:
// Fields in every vertex node
string name;
std::list<Vertex*> adjacencyList;
bool status;
int depth;
// Constructor which initializes the node
Vertex(string id)
{
name = id;
adjacencyList = list<Vertex*>();
status = false;
depth =0;
}
// Function to add edges by pushing the vertices to its adjacency list
void addEdge(Vertex *v)
{
adjacencyList.push_back(v);
}
};
class Graph{
public:
// Fields of the Graph node
int N;
std::list<Vertex> vertexList;
// Functions to be implemented
int Connection(Vertex,Vertex);
Graph(int n){ // Constructor
N = n;
vertexList = list<Vertex>();
}
/* This function first checks whether the vertex has been already added
to Vertex List of the Graph. If not found it would create the vertex
node and push the node into Vertex List. Then the edges are added by
updating the adjacency list of respective vertices. */
void addEdge(string to, string from ){
if(find(to))
{
Vertex entity_1 = Vertex(to); // New vertex node creation
vertexList.push_back(entity_1); // Pushing to the Vertex List
}
if(find(from))
{
Vertex entity_2 = Vertex(from);
vertexList.push_back(entity_2);
}
Vertex *v1 = &(*(find_it(to)));
Vertex *v2 = &(*(find_it(from)));
v1->addEdge(v2); // Updating respective adjacency list
v2->addEdge(v1);
}
// Function to check whether the vertex is already added in the Vertex List
int find(string check)
{
list<Vertex>::iterator it;
it = find_it(check);
if(it==vertexList.end())
return 1;
else
return 0;
}
// Function which returns pointer to a Vertex in the Vertex List
list<Vertex>::iterator find_it(string check)
{
list<Vertex>::iterator it;
for (it = vertexList.begin(); it != vertexList.end(); it++)
if((check.compare(it->name))==0)
break;
return it;
}
};
int main()
{
int numVertices,numEdges,i,result;
string to,from,queryTo,queryFrom;
cin>>numVertices>>numEdges;
Graph G = Graph(numVertices); // Creating the Graph object
for( i=0;i<numEdges;i++)
{
cin>>to>>from;
G.addEdge(to,from); // Adding Edges to Graph
}
cin>>queryTo>>queryFrom;
// The function you have to write is called here where the address of vertex
// node is passed.
result = G.Connection((*(G.find_it(queryTo))),(*(G.find_it(queryFrom))));
if(!result)
cout<<"No Connection";
else
cout<<"Degree : "<<result;
return 0;
}
int Graph::Connection(Vertex v1,Vertex v2)
{
// Mark all the vertices as not visited
Vertex s=Vertex("xx");
int i=0;
//list<Vertex>::iterator it;
Vertex *temp=&(*(vertexList.begin()));
while(!temp)
temp->status = false,++temp;
// Create a queue for BFS
list<Vertex> queue;
// Mark the current node as visited and enqueue it
v1.status=true;
queue.push_back(v1);
// it will be used to get all adjacent vertices of a vertex
int depth;
while (!queue.empty())
{
depth=0;
// Dequeue a vertex from queue and print it
s = queue.front();
queue.pop_front();
// Get all adjacent vertices of the dequeued vertex s
// If a adjacent has not been visited, then mark it visited
// and enqueue it
temp=s.adjacencyList.front();
while(temp!=NULL)
{
++depth;
// If this adjacent node is the destination node, then return true
if ((v2.name.compare(temp->name))==0)
{
v2.depth=depth;
return v2.depth;
}
// Else, continue to do BFS
if(temp->status==false)
{
temp->status = true;
queue.push_back(*temp);
}
++temp;
}
}
return 0;
}
I'm going to assume that the degree of connection you are trying to compute is the shortest path distance between nodes (with uniform edge costs). You can use Floyd-Warshall to pre-process the graph and answer queries in O(1) time. It's really simple to implement.
int a[N][N]; /* adjacency matrix where N is max node count */
/* build graph here and init distances between distinct nodes to +INFINITY */
/* n is number of nodes */
for(int k = 0; k < n; k++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
dist[i][j] = min(dist[i][j], dist[i][k]+dist[k][j]);
To answer a query (x,y) you print dist[x][y].
Your BFS solution looks unnecessarily complicated. Use a vector<in> g[N] to represent your graph. Add an edge x->y with g[x].push_back(y). BFS would look like:
queue<int> Q;
Q.push(s); /* start node */
for(int i = 0; i < n; i++)
{ dist[i] = INFINITY;
}
dist[s] = 0; /* distance to s is set to 0 */
while(Q.empty() == false)
{ int x = Q.front(); Q.pop();
for(int i = 0; i < g[x].size(); i++)
{ int y = g[x][i];
/* process edge x->y */
if(dist[y] == INFINITY)
{ dist[y] = dist[x] + 1;
Q.push(y);
}
}
}
distance between s and any other node t is dist[s][t].
Your code also crashes in a segmentation fault, if you try to find a connection with degree 1. Given your graph try to find "Harry Krax".
I think the mistake is using a pointer Vertex * temp = temp=s.adjacencyList.front(); and later trying to access the next Vertex by ++temp;.
This is not how std::list in combination with pointers work.
If you want to access the next Vertex with ++temp, than you might want to use iterators std::list<x>::iterator temp.
What you are trying to do works with arrays like int a[N], because the elements of an array are adjacent in memory.
With int * aptr = a. ++aptr says that temp is to move to another location in memory that is the size of one int further away.
std::list<x> does not do this. Here the elements can be scatter at different places in memory. (Simplified) it's value and pointers to the previous and next element are stored.

Linked-List C++,

The input is in the following format
5
1 2 9.0
1 3 12.0
2 4 18.0
2 3 6.0
2 5 20.0
3 5 15.0
0
1 5
The first number is the number of vertexes in the graph. Then next lines up to 0 are the edges of the graph. With the first and second numbers being the vertexes and the third being how far the edge is between them. Trying to read in the data and store the edges into there locations in the List adjacency for that vertex. This example would make a graph with five vertexes with edges from 1 to 2&3. 2 to 4&3&1 etc. I do not know if the format for storing into the list in my readIn function is correct (myGraph.vertexInfo[p1].adjacency -> vertex=p2;) .
Is myGraph.vertexInfo[p1].adjacency -> vertex=p2; the correct way to store it? Ff not how I would store the info into the adjacency lists for each vertex? Also I am getting a Segmentation fault after entering four numbers.
#include <cstdio>
using namespace std;
struct ListCell
{
ListCell* next;
int vertex;
double weight;
ListCell(int v, double w, ListCell* nxt)
{
vertex = v;
weight = w;
next = nxt;
}
};
typedef ListCell* List;
struct Vertex
{
bool signaled;
long distance;
List adjacency;
};
struct Graph
{
int numVertices;
Vertex* vertexInfo;
Graph(int n)
{
numVertices = n;
vertexInfo = new Vertex[n+1];
for(int i = 1; i <= n; i++)
{
vertexInfo[i].signaled = false;
}
}
};
//==============================================================
// readIn
//==============================================================
//
//==============================================================
void readIn()
{
int g;
int p1;
int p2;
float edge;
scanf("%i ", &g);
Graph myGraph(g);
scanf("%i", &p1);
while(p1 != 0)
{
scanf("%i", &p2);
scanf("%f", &edge);
myGraph.vertexInfo[p1].adjacency -> vertex=p2;
myGraph.vertexInfo[p2].adjacency -> vertex=p1;
myGraph.vertexInfo[p1].adjacency -> weight=edge;
myGraph.vertexInfo[p2].adjacency -> weight=edge;
scanf("%i", &p1);
}
}
//==============================================================
// main
//==============================================================
int main(int argc, char** argv)
{
readIn();
return 0;
}
I think you're trying to initialize a graph with g as an argument to the constructor but you have something confused -
Graph(g);
should be
Graph myGraph(g);
This is the problem:
void readIn()
{
int g;
...
Graph(g);
The compiler doesn't like it that you first said "g is an int" and then said "g is a graph".
You should place the readIn function inside your Graph struct so it can acces its members. And also you can use
Graph graph(g);
instead of
Graph(g);

Creating array of structs in C++

I'm having a newbie problem in C++.
I have a struct Edge defined as following:
struct Edge {
int position[4];
int average;
};
Now I need to create a lot of these structs and I created a helper-method for that, that creates an array of these structs based on some parameters:
Edge* createEdges(int some_parameters){
Edge *edges = new Edge[8];
for(int i = 0 ; i < 8; i++){
Edge edge;
edge.position[0] = 1; //fill the rest of the edge array in the same manner
edge.average = 10;
edges[i] = edge;
}
return edges;
}
However when I now call: Edge *edges = createEdges(int some_parameters) there is no sensible data in the Edge array (out of scope?).
I think I'm mixing up some things here but I would prefer if I can make this work without resorting to the vector datastructures. Is this the normal way of handling this or should I declare the edge array myself and pass it to the helper method to fill it up?
Edit:
First of all, I want to thank everyone for there comments/hints/tips/advice/... they have helped me to find the problem that I overlooked so easily.
After I seen the replies that the code should work, I tested the simplified code aswell (something I should have done in the 1st place) and surprisingly, it worked! So then I checked to see why my real code didn't work and the simplified version did.
My real code looked like this:
Edge* createEdges(int some_parameters){
Edge* edges = new Edge[8];
if(some_parameter != 0){
//create the edges as in my 1st snippet
return NULL; //doh, should return edges here !
} else {
return NULL;
}
}
The reason why I had not seen that I simply returned the wrong value (NULL) was because the debugger showed me some 0xf6f6f6 addressess with some negative values for edge.position (something I don't quite understand, it should've just show me 0x000000, perhaps I was just imagining things).
All in all, this was an important lesson in why to never code after 3am, nothing good will come of it!
It's C++ use std::vector:
std::vector<Edge> createEdges(int some_parameters){
std::vector<Edge> edges;
for(int i = 0 ; i < 8; i++){
Edge edge;
edge.position[0] = 1;
edge.average = 10;
edges.push_back(edge);
}
return edges;
}
What you have here works fine. What I feel you are forgetting, is that when you call
Edge *edges = createEdges(int some_parameters)
that edges variable is a pointer to the first element in your list. If you were to then do:
edges[0]
or:
edges[1]
you would see that these are different values, and you need to now loop through to access the array. Just keep in mind that you do not go passed the end of your array during a loop. This is why most people say to use vectors, because you can use more of the safety features with an iterator.
Welcome to C++! The helper-method for creating instances of a class (a struct in C++ is a class where all the fields are public) is called a constructor.
Here is how I would create instances of the edge class, using a constructor.
class Edge {
public:
int position[4];
int average;
Edge();
};
Edge::Edge() //constructor
{
position[0] = 1;//fill the rest of the edge array in the same manner
average = 10;
}
int main()
{
Edge* myEdge = new Edge(); //constructor called
Edge* myEdges[8];
for (int i = 0; i < 8; i++)
{
myEdges[i] = new Edge();
}
return 0;
}
Here is a bit modified version that creates edges in the function, and returns a vector containing all created edges.
#include <iostream>
#include <vector>
struct Edge {
int position[4];
int average;
};
std::vector< Edge > createEdges(int some_parameters){
std::vector< Edge > edges( 8 );
for(int i = 0 ; i < 8; i++){
const Edge edge{ { 1, 0, 0, 0 }, 10 };
edges[i] = edge;
}
return edges;
}
int main()
{
auto e( createEdges(5));
std::cout<<e[0].average<<std::endl;
}
There are few modifications :
Instead of allocating an array of edges, and returning pointer, I return vector
the way edge objects are created, and initialized (I think this is what is asked)

How to sort a Vector of type <class*>? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C++ how to sort vector<class *> with operator <
Hello everyone!
Please i am trying to sort a vector of type "class" based on one of its data members. As follows:
The Header File: (Undirected_Graph.h)
#ifndef UNDIRECTED_GRAPH_H
#define UNDIRECTED_GRAPH_H
#include <vector>
using std::vector;
#include <climits>
class Edge;
class Node
{
public:
Node(int); //The constructor.
int id; //For the id of the node.
bool visited; //For checking visited nodes.
int distance;
vector <Edge*> adj; //The adjacent nodes.
};
class Edge
{
public:
Edge(Node*, Node*, int); //The constructor.
Node* start_Node; //The start_Node start of the edge.
Node* end_Node; //The end of the edge.
int w; //The weight of the edge.
bool isConnected(Node* node1, Node* node2) //Checks if the nodes are connected.
{
return((node1 == this->start_Node && node2 == this->end_Node) ||
(node1 == this->end_Node && node2 == this->start_Node));
}
};
class Graph
{
public:
Graph(int); //The Constructor.
int max_Nodes; //Maximum Number of allowed Nodes.
vector <Edge*> edges_List; //For storing the edges of the graph.
vector <Node*> nodes_List; //For storing the nodes of the graph.
void insertEdge(int, int, int);
int getNumNodes();
int getNumEdges();
};
#endif
The Implementation File: (Undirected_Graph.cpp)
#include "Undirected_Graph.h"
Node::Node(int id_Num)
{
id = id_Num;
visited = 0;
distance = INT_MAX;
}
Edge::Edge(Node* a, Node* b, int weight)
{
start_Node = a;
end_Node = b;
w = weight;
}
Graph::Graph(int size)
{
max_Nodes = size;
for (int i = 1; i <= max_Nodes; ++i)
{
Node* temp = new Node(i);
nodes_List.push_back(temp);
}
}
void Graph::insertEdge(int x, int y, int w)
{
Node* a = nodes_List[x-1];
Node* b = nodes_List[y-1];
Edge* edge1 = new Edge(a, b, w);
Edge* edge2 = new Edge(b, a, w);
edges_List.push_back(edge1);
a->adj.push_back(edge1);
b->adj.push_back(edge2);
}
int Graph::getNumNodes()
{
return max_Nodes;
}
int Graph::getNumEdges()
{
return edges_List.size();
}
Now in the above code, after creating several nodes and edges, i need to sort the edges of this graph based on their weight. I am studying a way to implement Kruskal algorithm so i though of sorting the edges first based on their weight.
sort (myGraph.edges_List[index].begin(), myGraph.edges_List[index].end());
obviously does not work! since the vector edges_List is of type "Edge".
Assuming that (myGraph is an object of the class).
I was wondering if there is any good technique to do that?
Thanks in advance for your help! Any suggestions or ideas are greatly appreciated!
By default, std::sort uses using operator<, but you can also supply a comparison function object.
So:
bool your_comparer(const Edge * left, const Edge * right)
{
// return true if left should come before right, false otherwise
}
// ...
sort (myGraph.edges_List.begin(), myGraph.edges_List.end(), your_comparer);
Another way is usage std::set container for storing your objects. And you always will have sorted container. All you need is define operator < for stored classes.
Usage vector with push_back is not effective way in terms of time. It cause unnecessary memory rellocations.