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;}
Related
So I've been trying to implement Kruskal's algorithm, first I want to make clear the question is not related to the implementation of the algorithm. I've created one graph.hpp file, one kruskalsAlgo.hpp and main.cpp as follows respectively:
#pragma once
struct Edge
{
int source;
int destination;
int weight;
};
struct Graph
{
int V;
int E;
Edge* edge;
};
Graph* create_graph(int V, int E)
{
Graph* graph = new Graph;
graph -> V = V;
graph -> E = E;
graph -> edge = new Edge[E];
return graph;
}
#include <stdlib.h>
#include <tuple>
#include "../Graph/Graph.hpp"
class Kruskals_Algo
{
private:
struct subset
{
int parent;
int rank;
};
void make_set(subset*, int);
int find_set(subset*, int);
void _union(subset*, int, int);
public:
Edge* kruskal(Graph*);
void print_kruskals_MST(Edge*, int);
};
void Kruskals_Algo::make_set(subset* subsets, int V)
{
subsets[V].parent = V;
subsets[V].rank = 0;
}
int Kruskals_Algo::find_set(subset* subsets, int V)
{
if(subsets[V].parent != V)
subsets[V].parent = find_set(subsets, subsets[V].parent);
return subsets[V].parent;
}
void Kruskals_Algo::_union(subset* subsets, int x, int y)
{
int xroot = find_set(subsets, x);
int yroot = find_set(subsets, y);
if(subsets[xroot].rank < subsets[yroot].rank)
subsets[xroot].parent = yroot;
else if(subsets[xroot].rank > subsets[yroot].rank)
subsets[yroot].parent = xroot;
else
{
subsets[yroot].parent = xroot;
subsets[xroot].rank++;
}
}
inline int myComp(const void* a, const void* b)
{
Edge* a1 = (Edge*)a;
Edge* b1 = (Edge*)b;
return a1 -> weight > b1 -> weight;
}
Edge* Kruskals_Algo::kruskal(Graph* graph)
{
int V = graph -> V;
Edge result[V];
Edge* result_ptr = result;
int e = 0;
int i = 0;
qsort(graph -> edge, graph -> E, sizeof(graph -> edge[0]), myComp);
subset* subsets = new subset[(V * sizeof(subset))];
for (int v = 0; v < V; ++v)
make_set(subsets, v);
while(e < V - 1 && i < graph -> E)
{
Edge next_edge = graph -> edge[i++];
int x = find_set(subsets, next_edge.source);
int y = find_set(subsets, next_edge.destination);
if (x != y)
{
result[e++] = next_edge;
_union(subsets, x, y);
}
}
//return std::make_tuple(res, e);
return result_ptr;
}
void Kruskals_Algo::print_kruskals_MST(Edge* r, int e)
{
int minimumCost = 0;
for(int i=0; i<e; ++i)
{
std::cout << r[i].source << " -- "
<< r[i].destination << " == "
<< r[i].weight << std::endl;
minimumCost = minimumCost + r[i].weight;
}
std::cout << "Minimum Cost Spanning Tree: " << minimumCost << std::endl;
}
#include <iostream>
#include "Graph/Graph.hpp"
#include "Kruskals_Algo/kruskalsAlgo.hpp"
//#include "Prims_Algo/primsAlgo.hpp"
using namespace std;
class GreedyAlgos
{
public:
void kruskals_mst();
//void prims_mst();
};
void GreedyAlgos::kruskals_mst()
{
Kruskals_Algo kr;
int V;
int E;
int source, destination, weight;
cout << "\nEnter the number of vertices: ";
cin >> V;
cout << "\nEnter the number of edges: ";
cin >> E;
Edge* res;
Graph* graph = create_graph(V, E);
for(int i=0; i<E; i++)
{
cout << "\nEnter source, destinstion and weight: ";
cin >> source >> destination >> weight;
graph -> edge[i].source = source;
graph -> edge[i].destination = destination;
graph -> edge[i].weight = weight;
}
//std::tie(result, E) = kr.kruskal(graph);
res = kr.kruskal(graph);
kr.print_kruskals_MST(res, E);
}
int main()
{
int choice;
GreedyAlgos greedy;
greedy.kruskals_mst();
return 0;
}
So my question here is when I debug the program the values in Edge result[V], which is a structure array, are calculated correctly, at position [0] [1] [2] as in the following picture:
but when the function print_kruskals_MST(res, E) is called from the main the values printed are different:
Is there any pointer thing that I'm doing wrong?
Thanks in advance!
P.S. Ignore the comments!
This answer might not answer your question directly but it should shed some light on the problem.
First of all, yes you have a lot of pointer problems...
Secondly, pair ANY use of the new operator with the delete operator. As it stands, you have a bunch of memory leaks.
Also, why create_graph? Create a constructor for Graph instead (and a destructor since the class has an Edge* edge it needs to take care of).
struct Graph
{
int V;
int E;
Edge* edge;
// constructor
Graph(int V, int E)
{
this->V = V;
this->E = E;
this->edge = new Edge[E];
}
// destructor
~Graph()
{
// nullify the member variable before deleting its memory is just a safety measure pertaining to multithreading.
Edge* _edge = this->edge;
this->edge = nullptr;
delete _edge;
}
};
Then change Graph* graph = create_graph(V, E); into Graph* graph = new Graph(V, E); and do delete graph when you're done using it.
Make sure you remove all memory leaks and we can go on to discussing referencing the correct data (f.ex. by me changing my answer).
I am trying to implement kruskal's algo. togather with bfs and dfs. i wrote my code to print the adjancey list and to show the bfs and dfs and now i am facing problem with writing the code for kruskal's algorithm i kind of newbie in using maps and templates. i don't know how to pass the values in the kruskals algorithm and i m constantly getting errors.
here is the code that i have written.
#include<iostream>
#include<map>
#include<queue>
#include<list>
#include<cstring>
#include<algorithm>
using namespace std;
template<typename T>
class Graph{
private:
map<T,list<pair<T,int>>> l;
void DFSHelper(T node,map<T,bool> &visited){
cout<<node<<" -> ";
visited[node]=true;
for(auto neighbours:l[node]){
if(!visited[neighbours.first]){
DFSHelper(neighbours.first,visited);
}
}
}
public:
void add(T A,T B,bool bi,int wi){
l[A].push_back(make_pair(B,wi));
if(bi == true){
l[B].push_back(make_pair(A,wi));
}
}
void print(){
for(auto c:l){
int c1 = c.first;
list<pair<int,int>> n = c.second;
cout<<c1<<" -> ";
for(auto k:n){
int dest = k.first;
int dist = k.second;
cout<<dest<<"("<<dist<<") ";
}
cout<<endl;
}
}
void bfs(T src){
map<T,bool> visited;
queue<T> q;
q.push(src);
visited[src] = true;
while(!q.empty()){
T node = q.front();
q.pop();
cout<<node<<" -> ";
for(auto children:l[node]){
if(!visited[children.first]){
visited[children.first]=true;
q.push(children.first);
}
}
}
}
void dfs(T src){
map<T,bool> visited;
int component = 1;
DFSHelper(src,visited);
}
void cmp(T src,T end){
return src.second.second<end.second.second;
}
void kruskals(){
}
};
int main(){
Graph<int> g;
g.add(1,2,true,20);
g.add(1,3,true,30);
g.add(2,4,true,50);
g.add(3,4,true,10);
g.add(4,5,true,60);
g.add(5,1,false,35);
g.print();
cout<<endl;
cout<<"BFS :- ";
g.bfs(1);
cout<<endl;
cout<<"DFS :- ";
g.dfs(1);
g.kruskals();
}
Your graph appears to be directed due to the uni-directional edge 5->1. Kruskal's algorithm only works for undirected graphs. (Why?)
In Kruskal's algorithm you need the edges sorted in non-decreasing order of edge-weights. Hence you can either maintain an extra data structure alongwith the map l and insert to it in the add() function or create it in the kruskals() function itself.
Next you need a data structure to query if any two nodes of the graph belong to two different components or not. Here two nodes are said to be in the same component if you can reach one node to the other by only considering edges encountered till that particular iteration of the Kruskal's algorithm. A Disjoint Set Union can do that efficiently.
Here is an implementation, where I use the set edge_weights to store the edges sorted by weight:
#include<iostream>
#include<map>
#include<queue>
#include<list>
#include<cstring>
#include<algorithm>
#include <set> // Added
using namespace std;
template<typename T>
class DisjointSetUnion {
map<T, T> parent;
map<T, int> sz; // stores sizes of component
public:
void make_set(T v) {
parent[v] = v;
}
T find_set(T x) {
if(x != parent[x]) parent[x] = find_set(parent[x]);
return parent[x];
}
void merge_sets(T x, T y) {
int px = find_set(x), py = find_set(y);
if(sz[px] > sz[py]) parent[py] = px;
else parent[px] = py;
if(sz[py] == sz[px]) sz[py]++;
}
};
template<typename T>
class Graph{
private:
map<T,list<pair<T,int>>> l;
set<pair<int, pair<T, T>>> edge_weights; // no parallel (or duplicate) edges exist
void DFSHelper(T node,map<T,bool> &visited){
cout<<node<<" -> ";
visited[node]=true;
for(auto neighbours:l[node]){
if(!visited[neighbours.first]){
DFSHelper(neighbours.first,visited);
}
}
}
public:
void add(T A,T B,bool bi,int wi){
l[A].push_back(make_pair(B,wi));
if(bi == true){
l[B].push_back(make_pair(A,wi));
edge_weights.insert(make_pair(wi, make_pair(A, B))); // Added
}
}
void print(){
for(auto c:l){
int c1 = c.first;
list<pair<int,int>> n = c.second;
cout<<c1<<" -> ";
for(auto k:n){
int dest = k.first;
int dist = k.second;
cout<<dest<<"("<<dist<<") ";
}
cout<<endl;
}
}
void bfs(T src){
map<T,bool> visited;
queue<T> q;
q.push(src);
visited[src] = true;
while(!q.empty()){
T node = q.front();
q.pop();
cout<<node<<" -> ";
for(auto children:l[node]){
if(!visited[children.first]){
visited[children.first]=true;
q.push(children.first);
}
}
}
}
void dfs(T src){
map<T,bool> visited;
int component = 1;
DFSHelper(src,visited);
}
void cmp(T src,T end){
return src.second.second<end.second.second;
}
void kruskals(){
DisjointSetUnion<int> dsu;
// make singleton components of each node
for(auto it: l) {
T u = it.first;
dsu.make_set(u);
}
// iterate over all edges in sorted order
for(auto ed: edge_weights) {
int w = ed.first;
T u = ed.second.first, v = ed.second.second;
// if they belong to different components then they are
// part of the MST, otherwise they create a cycle
if(dsu.find_set(u) != dsu.find_set(v)) {
// this edge is part of the MST, do what you want to do with it!
cout << "(" << u << "," << v << "," << w << "), ";
// merge the two different components
dsu.merge_sets(u, v);
}
}
}
};
int main(){
Graph<int> g;
g.add(1,2,true,20);
g.add(1,3,true,30);
g.add(2,4,true,50);
g.add(3,4,true,10);
g.add(4,5,true,60);
// Removed unidirectional edge below
// g.add(5,1,false,35);
g.print();
cout<<endl;
cout<<"BFS :- ";
g.bfs(1);
cout<<endl;
cout<<"DFS :- ";
g.dfs(1);
cout << endl;
cout << "Edges in MST (u,v,w): ";
g.kruskals();
cout << endl;
}
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!
I'm trying to detect and print a cycle in an undirected path, starting from a given vertex. So far, the path is recorded in a vector. The code seems to work, but there's one more vertex reported than it should be.
For the given example, one expected path would be: -1,6,0,5,3 which also put out: -1,6,0,5,3,2 but there's one more vertex than expected.
Maybe somebody has an idea how this can be fixed.
Thanks in advance!
#include <vector>
#include <iostream>
class Vertex
{
public:
Vertex() {};
Vertex(int x, int y, bool visited) : _x(x), _y(y){}
int _x;
int _y;
};
class Edge
{
public:
Edge(Vertex* from, Vertex* to): _from(from), _to(to){}
Vertex* _from;
Vertex* _to;
};
class MyGraph
{
public:
void addVertex(int x, int y, bool visited);
void addEdge(Vertex* vp1, Vertex* vp2);
bool dfs(int v, int p);
std::vector<std::vector<int>> g;
bool* visited;
std::vector<Edge> edges;
std::vector<Vertex> vertices;
std::vector<int>path;
};
void MyGraph::addVertex(int x, int y, bool visited)
{
Vertex v = Vertex(x, y, visited);
this->vertices.push_back(v);
}
void MyGraph::addEdge(Vertex* vp1, Vertex* vp2)
{
Edge e = Edge(vp1, vp2);
this->edges.push_back(e);
}
bool MyGraph::dfs(int v, int p)
{
visited[v] = true;
this->path.push_back(p);
for (int i = 0; i < (int)g[v].size(); i++)
{
if (!visited[g[v][i]])
{
dfs(g[v][i], v);
return true;
}
if (g[v][i] != p)
{
return true;
}
}
this->path.pop_back();
return false;
}
int main(int argc, char** argv)
{
MyGraph mg;
mg.addVertex(3, 0, false);
mg.addVertex(0, 1, false);
mg.addVertex(2, 1, false);
mg.addVertex(0, 2, false);
mg.addVertex(1, 2, false);
mg.addVertex(3, 2, false);
mg.addVertex(0, 0, false);
mg.g.resize(mg.vertices.size());
mg.g[0].push_back(5);
mg.g[0].push_back(6);
mg.g[1].push_back(2);
mg.g[1].push_back(3);
mg.g[1].push_back(6);
mg.g[2].push_back(1);
mg.g[3].push_back(2);
mg.g[3].push_back(4);
mg.g[3].push_back(5);
mg.g[3].push_back(6);
mg.g[4].push_back(3);
mg.g[4].push_back(5);
mg.g[5].push_back(0);
mg.g[5].push_back(3);
mg.g[5].push_back(4);
mg.g[6].push_back(0);
mg.g[6].push_back(1);
mg.g[6].push_back(3);
// expected path: 6,0,5,3
mg.visited = new bool[mg.vertices.size()]{false};
std::vector<int> pppath;
std::cout << mg.dfs(6, -1) << std::endl;
for (auto n : mg.path)
{
std::cout << n << ",";
}
return 0;
}
Thanks for your input. The problem has been solved. The push_back has to happen a line later in the for loop. Nonetheless, the code has the problem that the adjacency list has to be created on a certain order to avoid jumping back directly to the starting point.
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.