I'm doing some work on data structures, just to learn. Right now I have an admittedly very basic graph data structure.
I can create the graph with a predefined size, and then add edges to/from each vertex (un-directed). Here is the code so far:
graph.h
#pragma once
#include "stdafx.h"
#include <vector>
#include <iostream>
#include <algorithm>
class Graph {
int vertices; // num of vertices in graph
std::vector<int> *adjList;
public:
Graph(int vertices);
void addEdge(int v, int w);
void printGraph();
};
Graph::Graph(int vertices) {
this->vertices = vertices;
adjList = new std::vector<int>[vertices];
}
void Graph::addEdge(int v, int w) {
adjList[v].push_back(w);
}
void Graph::printGraph() {
for (int i = 0; i < adjList->size(); ++i) {
}
}
graph.cpp
#include "stdafx.h"
#include "graph.h"
int main()
{
Graph graph(4);
graph.addEdge(0, 1); //counter starts at 0
graph.addEdge(0, 2);
graph.addEdge(2, 1);
graph.addEdge(2, 3);
return 0;
}
This works fairly well, however I would also like to add nodes after the graph object has already been created. I really can't figure out how to do this.
Any sort of guidance towards this (as well as general improvements to the code) will be greatly appreciated.
Use a vector to store your adjacency list and resize it when required:
std::vector<std::vector<int>> adjList;
Don't allocate it with new, don't delete it, use standard containers!
Related
This is the representation of an adjacency list.When i try to print the graph the loop does not terminate and keeps repeating weird values again and again.What is wrong in the loops
#include<iostream>
#include<list>
using namespace std;
class Graph{
int V;
list<int> *l;
public:
Graph(int v){
V=v;
l=new list<int>[V];//Array of linked lists
}
void addEdge(int u,int v, bool bidirec=true){
l[u].push_back(v);
if(bidirec){//condition for bidirectional graph
l[v].push_back(u);
}
}
void printAdjList(){
for(int i=0;i<V;i++){
cout<<i<<"-->";
for(int vertex:l[i]){//For each loop
cout<<vertex<<",";
}
cout<<endl;
}
}
};
int main(){
Graph g(5);//graph with 5 vertices
g.addEdge(0,1);//adding edges
g.addEdge(0,4);
g.addEdge(4,3);
g.addEdge(1,4);
g.addEdge(1,2);
g.addEdge(2,3);
g.printAdjList();
return 0;
}
Im trying to write a adjacency matrix representation using vectors of integer vectors , therefore vector> . However when I add members to the vector and later try and print those values nothing has changed. Most likely it has to do with "pass by value" however I have used "pass by reference" to the best of my knowledge.
Here is my header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
the cpp implementation file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix.push_back(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
for (int i=0; i< vertex_matrix.size(); i++)
{
for (int j = 0; j < vertex_matrix.size(); j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
When I use the print function I currently getting 0's.
How can I make this proper pass by reference, and have the updated values print.
Thanks
As stated in the comments, you are creating a copy of your column and then modifying the copy. What you want to do is to make a reference to it.
vector<int>& columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
Or you can access the element directly.
if (vertex_matrix[v1-1][v2-1] == INT_MAX)
{
vertex_matrix[v1-1][v2-1] = weight;
}
In print_graph you are doing the same, but here you are not modifying anything so that works, but you are making an unnecessary copy for no reason which is not ideal.
A last point is that you are calling vertex_matrix.clear() in your destructor. This is redundant, when the vector goes out of scope it will clear itself up, so you don't need to manage that.
Im trying to create a adjacency representation of a graph.
I wrote a small program using vectors of vectors , however I keep getting "segmentation fault" but the compiler(clang++ version 5.0.1 on Windows) it seems wereever I try to access the vector vertex_matrix its giving a segmentation fault, why is it not being instantiated?
Here is the header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight);
void print_graph();
private:
std::vector<std::vector<int>> vertex_matrix;
int num_of_vertices;
int num_of_edges;
};
#endif
Here is the cpp implementation:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices)
{
if (_num_of_vertices==0)
{
_num_of_vertices=10;
}
for (int i = 0; i < _num_of_vertices; i++)
{
vertex_matrix[i]=(vector<int> (_num_of_vertices,INT_MAX));
}
}
graph::~graph()
{
vertex_matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight)
{
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = vertex_matrix[v1-1];
if (columnVector[v2-1] == INT_MAX)
{
columnVector[v2-1] = weight;
}
}
void graph::print_graph()
{
cout << "vertex_matrix size:" << vertex_matrix.size() << endl;
for (int i=0; i< num_of_vertices; i++)
{
for (int j = 0; j < num_of_vertices; j++)
{
//vertex_matrix[i][j]
std::vector<int> columnVector = vertex_matrix[i];
if (columnVector[j] != INT_MAX)
{
std::cout << columnVector[j] ;
}
else
{
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
Here is the main entry:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
_graph.add_edge(1,2,1);
_graph.add_edge(2,3,1);
_graph.add_edge(3,1,1);
_graph.add_edge(3,3,1);
_graph.add_edge(3,4,1);
_graph.add_edge(4,0,0);
_graph.print_graph();
}
I edited the above code to use pass by reference, however the matrix still prints as 0's.
Please help with pass by reference, updates below:
Header:
#ifndef GRAPH_MATRIX
#define GRAPH_MATRIX
#include <vector>
//header for graph represented via adjacency matrix with minimal functionality
class graph
{
public:
graph(int);
~graph();
void add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & matrix);
void print_graph();
std::vector<std::vector<int>> vertex_matrix;
private:
int num_of_vertices;
int num_of_edges;
};
#endif
Cpp file:
#include <iostream>
#include "graph_matrix.h"
#include <climits>
using namespace std;
//header for graph represented via adjacency matrix with minimal functionality
graph::graph(int _num_of_vertices) : num_of_vertices(_num_of_vertices) {
if (num_of_vertices == 0) {
num_of_vertices = 10;
}
for (int i = 0; i < num_of_vertices; i++) {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.push_back(vector<int> (num_of_vertices, INT_MAX));
}
}
graph::~graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
matrix.clear();
}
void graph::add_edge(int v1, int v2, int weight,std::vector<std::vector<int>> & _matrix) {
//vertex_matrix[v1-1][v2-1] == INT_MAX
vector<int> columnVector = _matrix[v1 - 1];
if (columnVector[v2 - 1] == INT_MAX) {
columnVector[v2 - 1] = weight;
}
}
void graph::print_graph() {
std::vector<std::vector<int>>& matrix = vertex_matrix;
for (int i = 0; i < matrix.size(); i++) {
for (int j = 0; j < matrix.size(); j++) {
//vertex_matrix[i][j]
std::vector<int> columnVector = matrix[i];
if (columnVector[j] != INT_MAX) {
std::cout << columnVector[j];
} else {
std::cout << "0";
}
}
std::cout << endl;
}//end for printing
}
main:
#include <iostream>
#include "graph_matrix.h"
using namespace std;
int main ()
{
std::cout << " Matrix representation of graph" << std::endl;
graph _graph(4);
std::vector<std::vector<int>>& m = _graph.vertex_matrix;
_graph.add_edge(1,2,1,m);
_graph.add_edge(2,3,1,m);
_graph.add_edge(3,1,1,m);
_graph.add_edge(3,3,1,m);
_graph.add_edge(3,4,1,m);
_graph.add_edge(4,0,0,m);
_graph.print_graph();
}
Any help will be appreciated.
Thanks
You create an empty vector and then try to access elements in it. Change your constructor to
graph::graph(size_t _num_of_vertices) :
vertex_matrix(
std::vector<std::vector<int>>(
_num_of_vertices,std::vector<int>(_num_of_vertices)
)
)
{}
to create a correctly sized vector.
Also in case _num_vertices == 0 you set it to 10 but thats after you initialized the member num_vertices so you leave the object in an inconsistent state. There are different ways to fix that, I would probably just throw an exception when the number of vertices passed is zero, or just ignore it. User wants a zero sized matrix? Why not?
Moreover the size should be unsigned not signed, there is size_t for container sizes. Even better you shouldnt have that member at all, because a vector already knows its size, the only reason to repeat that information is to introduce mistakes ;)
class graph
{
int v;
list<int> *adj;
void dfsutil(int v,bool visited []);
public:
graph(int v)
{
this->v=v;
//adj = new list<int>[v];
adj = (list<int> *)malloc(v*sizeof(list<int>));
}
void addedge(int v,int w);
void dfs(int v);
};
void graph::addedge(int v,int w)
{
adj[v].push_back(w);
}
void graph::dfsutil(int v,bool visited[])
{
list<int>::iterator i;
cout<<v<<" ";
visited[v]=true;
for(i=adj[v].begin();i!=adj[v].end();i++)
{
if(!visited[*i])
dfsutil(*i,visited);
}
}
void graph::dfs(int v)
{
int i=0;
bool visited[this->v];
for(i=0;i<this->v;i++)
visited[i]=false;
dfsutil(v,visited);
for(i=0;i<v;i++)//this loop is required if there are multiple component of the graph
if(!visited[i])
dfsutil(i,visited);
}
int main()
{
// Create a graph given in the above diagram
graph g(4);
g.addedge(0, 1);
g.addedge(0, 2);
g.addedge(1, 2);
g.addedge(2, 0);
g.addedge(2, 3);
g.addedge(3, 3);
cout << "Following is Depth First Traversal (starting from vertex 2) \n";
g.dfs(2);
return 0;
}
in the above code if try to allocate space for list *adj using malloc as written above,it does not work fine whereas if we use new,it works fine as its written in commented part above,i cant figure out why
You did not create an array of std::list objects when you used malloc. All malloc does is allocate memory from the heap -- no objects are created. Thus attempting to use your std::list's as if they are created correctly will result in undefined behavior.
You should use a container such as std::vector to store your list objects:
#include <vector>
#include <list>
class graph
{
int v;
std::vector<std::list<int>> adj;
void dfsutil(int v,bool visited []);
public:
graph(int num) : v(num), adj(num) {}
void addedge(int v,int w);
void dfs(int v);
};
Note there is no need to allocate memory. The rest of your code should stay the same, since vector has an overloaded operator [] to access the items.
I am looking for solution to pick a number randomly from graph using c++.
For example I have a graph that add edge (one or more) between two vertices, how can I pick a number randomly?
some of code :
#include <iostream>
#include <list>
#include <queue>
using namespace std;
// Graph class represents a undirected graph using adjacency list representation
class Graph
{
private:
int V; // # of vertices
list<int> *adj; // Pointer to an array containing adjacency lists
public:
Graph(int V) // Constructor
{
this->V = V;
adj = new list<int>[V];
}
void addEdge(int v, int w); // function to add an edge to graph
void print(int v, int w); //function to display
};
void Graph::addEdge(int v, int w)
{
adj[v].push_front(w); // Add w to v’s list.
adj[w].push_front(v); // Add v to w’s list.
print(v, w);
}
void Graph::print(int v, int w) {
cout << v << " - " << w << endl;}
In the main:
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 3);
Sample output:
0 - 1 0 - 2 1 - 3
Use math lib. Rand function. Select random num and select (0 to number of edges-1) from list of edges, then select another random number and select that vertex of the edge, 0 or 1 (bottom/top vertex of edge)
#include <stdlib.h>
#include <iostream>
#include <list>
#include <queue>
using namespace std;
// Graph class represents a undirected graph using adjacency list representation
class Graph
{
private:
int V; // # of vertices
list<int> *adj; // Pointer to an array containing adjacency lists
public:
Graph(int V) // Constructor
{
this->V = V;
adj = new list<int>[V];
}
void addEdge(int v, int w); // function to add an edge to graph
void print(int v, int w); //function to display
};
void Graph::addEdge(int v, int w)
{
adj[v].push_front(w); // Add w to v’s list.
adj[w].push_front(v); // Add v to w’s list.
print(v, w);
}
int Graph::getRandomVertexFromEdge()
{
int list_size_divided_by_2 = adj.size() / 2;
int rEdge = (rand() % list_size_divided_by_2);
int rVW = (rand() % 1);
int ret = adj[(rEdge + rVW)];
//this will return a random vertex from a random edge;
print(rEdge,rVW);
return ret;
}
void Graph::print(int v, int w) {
cout << v << " - " << w << endl;}