Linked-List 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 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);

Related

Problems in evaluating subgraphs of a graph

Here is the question link.
Given an undirected graph. Density of a graph is |E|⁄|V|. Your task is to choose non-empty set of vertices V such that subgraph induced on V has maximal density and print this density. But if maximal density is strictly greater than 1, just print ">1".
Maximum number of vertices: 105
Maximum number of edges: 105
I just made a simple solution, but in this solution I can keep track of the whole graph, but how do I get the value of density for smaller subGraphs?
#include<iostream>
#include<vector>
using namespace std;
vector<int> adj[1000002]; // adjacency lists adj for storing graph edges
int node=0; // initializing for node value(vertices)
bool visited[100001]={false}; // keeps track of visited nodes(vertices)
int edge=-1;
int ans=-1;
int n; // keeps optimum value of no. of nodes
int e; // keeps optimum value of no. of edges
void dfs(int s)
{
node++;
edge++;
if(edge>0)
{
float dummy=(float)edge/(float)node;
if(dummy>ans)
{ans=dummy;
e=edge;
n=node;
}
}
visited[s]=true;
int t;
for(int i=0;i!=adj[s].size();i++)
{ t=adj[s][i];
if(visited[t]==false)
{
dfs(t);
}
}
}
int main()
{
long long v,ed,i,j,x,y;
cin>>v>>ed;
for(long long k=0;k<ed;k++)
{
cin>>x>>y;
adj[x].push_back(y);
adj[y].push_back(x);
}
if(ed>v)
cout<<">1"<<endl;
else{
for(i=1;i<=v;i++)
{
if(visited[i]==false)
{
node=0;
edge=-1;
dfs(i);
//cout<<e<<"/"<<n<<endl;
}
}
cout<<e<<"/"<<n<<endl;}
}
Follow these steps to get better result:
1.Do a dfs on each component to get the answer.
2.Avoid the floating point calculation you are doing and try all integer calculation.
3.No reason to use long long here with that range
Change the code to something like this should work:
#include<iostream>
#include<vector>
using namespace std;
vector<int> adj[1000002]; // adjacency lists adj for storing graph edges
int node=0; // initializing for node value(vertices)
bool visited[100001]={false}; // keeps track of visited nodes(vertices)
int edge=0;
void dfs(int s)
{
node++;
visited[s]=true;
int t;
edge+=adj[s].size();
for(int i=0;i!=adj[s].size();i++)
{
t=adj[s][i];
if(visited[t]==false)
{
dfs(t);
}
}
}
int main()
{
int v,ed,i,j,x,y;
cin>>v>>ed;
for(int k=0;k<ed;k++)
{
cin>>x>>y;
adj[x].push_back(y);
adj[y].push_back(x);
}
int mark[3]; mark[0]=mark[1]=mark[2]=0;
int mx_node=0;
for(i=1;i<=v;i++)
{
if(visited[i]==false)
{
node=0;
edge=0;
dfs(i);
edge/=2;
if(node>edge){
mark[0]=1;
mx_node=mx_node<node?node:mx_node;
}
else if(node==edge) mark[1]=1;
else mark[2]=1;
}
}
if(mark[2]) printf(">1\n");
else if(mark[1]) printf("1\n");
else printf("%d/%d\n",mx_node-1,mx_node);
}

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.

Segmentation Fault 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);
}
}

getting extra edge when removing the edges connected to the source vertex in a graph

last week i posted a code to calculate the shortest path in a graph using Dijkastra algorithm but it was very long and nobody was interesting in reading it completely so i deleted it, and now i am trying to simplify the code by going part by part, the code isn't complete yet, and i will cut part of the code here to focus on the first problem that i am facing so far.
briefly i have a class Graph it is going to be constructed by two other classes a vector of elements are instances of a class Edge , and another vector of elements of class Vertex , every vertex has an id , and every edge has two vertices and weight .
class Graph has a method its name is shortest takes two vertices as arguments the first one for the source of the graph and the second is for the destination.
So far i am trying to eliminate the edges that are connected to the source vertex , but i am getting an extra edge still in the vector edges it is connected to the source while all the other edges related to the source are removed.
to demonstrate the result , i initialized a graph has five vertices vers[0], vers[1], vers[2], vers[3], vers[4], and there are 10 edges connecting those vertices starting from eds[0], eds[1], ....eds[9].
the source vertex is vers[2] is connected by 4 edges , so when applying the method shortest as it is shown in the code below i should get rid of all those 4 edges and end with 6 edges , but the result was that i got rid of 3 edges and i have 7 edges remained, the result is as follows:
Hello, This is a graph
0____1 5
0____3 4
0____4 6
1____3 5
1____4 7
2____4 8
3____4 3
size of edges 7
size of vertices 5
as you can notice , there still an edge connected to the source which is 2 , the problem is in this edge (by the way 8 is the weight of the edge)
2____4 8
there is something wrong in the method shortest and specifically in the for loop , i hope you can help in finding my mistake.
Thanks in advance.
Here is the code
#include<iostream>
#include<vector>
#include <stdlib.h> // for rand()
using namespace std;
const unsigned int N = 5;
class Vertex
{
private:
unsigned int id; // the name of the vertex
public:
unsigned int get_id(){return id;};
void set_id(unsigned int value) {id = value;};
Vertex(unsigned int init_val = 0) :id (init_val){} // constructor
~Vertex() {}; // destructor
};
class Edge
{
private:
Vertex first_vertex; // a vertex on one side of the edge
Vertex second_vertex; // a vertex on the other side of the edge
unsigned int weight; // the value of the edge ( or its weight )
public:
unsigned int get_weight() {return weight;};
void set_weight(unsigned int value) {weight = value;};
Vertex get_ver_1(){return first_vertex;};
Vertex get_ver_2(){return second_vertex;};
void set_first_vertex(Vertex v1) {first_vertex = v1;};
void set_second_vertex(Vertex v2) {second_vertex = v2;};
Edge(const Vertex& vertex_1 = 0, const Vertex& vertex_2 = 0, unsigned int init_weight = 0)
: first_vertex(vertex_1), second_vertex(vertex_2), weight(init_weight)
{
}
~Edge() {} ; // destructor
};
class Graph
{
private:
std::vector<Vertex> vertices;
std::vector<Edge> edges;
public:
Graph(vector<Vertex> ver_vector, vector<Edge> edg_vector)
: vertices(ver_vector), edges(edg_vector){}
~Graph() {}
vector<Vertex> get_vertices(){return vertices;}
vector<Edge> get_edges(){return edges;}
void set_vertices(vector<Vertex> vector_value) {vertices = vector_value;}
void set_edges(vector<Edge> vector_ed_value) {edges = vector_ed_value;}
unsigned int shortest(Vertex src, Vertex dis);
};
unsigned int Graph::shortest(Vertex src, Vertex dis) {
vector<Vertex> ver_out;
vector<Edge> track;
for(unsigned int i = 0; i < edges.size(); ++i)
{
if((edges[i].get_ver_1().get_id() == src.get_id()) || (edges[i].get_ver_2().get_id() == src.get_id()))
{
track.push_back (edges[i]);
if(edges[i].get_ver_1().get_id() == src.get_id())
{ver_out.push_back (edges[i].get_ver_1());}
else
{ver_out.push_back (edges[i].get_ver_2());}
edges.erase(edges.begin() + i ); //****
}
};
}
int main()
{
cout<< "Hello, This is a graph"<< endl;
vector<Vertex> vers(5);
vers[0].set_id(0);
vers[1].set_id(1);
vers[2].set_id(2);
vers[3].set_id(3);
vers[4].set_id(4);
vector<Edge> eds(10);
eds[0].set_first_vertex(vers[0]);
eds[0].set_second_vertex(vers[1]);
eds[0].set_weight(5);
eds[1].set_first_vertex(vers[0]);
eds[1].set_second_vertex(vers[2]);
eds[1].set_weight(9);
eds[2].set_first_vertex(vers[0]);
eds[2].set_second_vertex(vers[3]);
eds[2].set_weight(4);
eds[3].set_first_vertex(vers[0]);
eds[3].set_second_vertex(vers[4]);
eds[3].set_weight(6);
eds[4].set_first_vertex(vers[1]);
eds[4].set_second_vertex(vers[2]);
eds[4].set_weight(2);
eds[5].set_first_vertex(vers[1]);
eds[5].set_second_vertex(vers[3]);
eds[5].set_weight(5);
eds[6].set_first_vertex(vers[1]);
eds[6].set_second_vertex(vers[4]);
eds[6].set_weight(7);
eds[7].set_first_vertex(vers[2]);
eds[7].set_second_vertex(vers[3]);
eds[7].set_weight(1);
eds[8].set_first_vertex(vers[2]);
eds[8].set_second_vertex(vers[4]);
eds[8].set_weight(8);
eds[9].set_first_vertex(vers[3]);
eds[9].set_second_vertex(vers[4]);
eds[9].set_weight(3);
unsigned int path;
Graph graf(vers, eds);
path = graf.shortest(vers[2], vers[4]);
cout<<graf.get_edges()[0].get_ver_1().get_id() <<"____"<<graf.get_edges()[0].get_ver_2().get_id() <<" "<<graf.get_edges()[0].get_weight()<< endl; //test
cout<<graf.get_edges()[1].get_ver_1().get_id() <<"____"<<graf.get_edges()[1].get_ver_2().get_id() <<" "<<graf.get_edges()[1].get_weight()<< endl; //test
cout<<graf.get_edges()[2].get_ver_1().get_id() <<"____"<<graf.get_edges()[2].get_ver_2().get_id() <<" "<<graf.get_edges()[2].get_weight()<< endl; //test
cout<<graf.get_edges()[3].get_ver_1().get_id() <<"____"<<graf.get_edges()[3].get_ver_2().get_id() <<" "<<graf.get_edges()[3].get_weight()<< endl; //test
cout<<graf.get_edges()[4].get_ver_1().get_id() <<"____"<<graf.get_edges()[4].get_ver_2().get_id() <<" "<<graf.get_edges()[4].get_weight()<< endl; //test
cout<<graf.get_edges()[5].get_ver_1().get_id() <<"____"<<graf.get_edges()[5].get_ver_2().get_id() <<" "<<graf.get_edges()[5].get_weight()<< endl; //test
cout<<graf.get_edges()[6].get_ver_1().get_id() <<"____"<<graf.get_edges()[6].get_ver_2().get_id() <<" "<<graf.get_edges()[6].get_weight()<< endl; //test
//cout<<graf.get_edges()[7].get_ver_1().get_id() <<"____"<<graf.get_edges()[7].get_ver_2().get_id() <<" "<<graf.get_edges()[7].get_weight()<< endl; //test
//cout<<graf.get_edges()[8].get_ver_1().get_id() <<"____"<<graf.get_edges()[8].get_ver_2().get_id() <<" "<<graf.get_edges()[8].get_weight()<< endl; //test
//cout<<graf.get_edges()[9].get_ver_1().get_id() <<"____"<<graf.get_edges()[9].get_ver_2().get_id() <<" "<<graf.get_edges()[9].get_weight()<< endl; //test
cout<<"size of edges"<<graf.get_edges().size()<< endl;
cout<<"size of vertices"<<graf.get_vertices().size()<< endl;
return 0;
}
This is because you are effectively skipping some vector elements in your Graph::shortest for loop because you are incrementing i even when you erase current element. Change it to something like this to fix the problem:
for (unsigned int i = 0; i < edges.size();) { // no ++i here
if ((edges[i].get_ver_1().get_id() == src.get_id()) || (edges[i].get_ver_2().get_id() == src.get_id())) {
track.push_back(edges[i]);
if (edges[i].get_ver_1().get_id() == src.get_id()) {
ver_out.push_back(edges[i].get_ver_1());
} else {
ver_out.push_back(edges[i].get_ver_2());
}
edges.erase(edges.begin() + i);
} else {
++i; // increment only if not erasing
}
}
Alternatively as per comment, using iterators:
for (auto i = edges.begin(); i != edges.end();) {
if ((i->get_ver_1().get_id() == src.get_id()) || (i->get_ver_2().get_id() == src.get_id())) {
track.push_back(*i);
if (i->get_ver_1().get_id() == src.get_id()) {
ver_out.push_back(i->get_ver_1());
} else {
ver_out.push_back(i->get_ver_2());
}
i = edges.erase(i);
} else {
i++;
}
}
You are also missing a return statement in that function.