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;
}
Related
Can anybody explain me, how to do Breadth first search in the graph that uses vector of linked lists ?
My Graph header file:
#include <string>
#include <iostream>
#include <map>
#include <vector>
using namespace std;
struct vertex {
string code;
vertex* next;
};
struct AdjList {
vertex *head;
AdjList(vertex* Given) {
head = Given;
}
};
class Graph {
map<string, string> associations;
int nodeNum; //amount of nodes or size of the graph;
vector<AdjList> adjList;
public:
Graph(int NodeNum);
~Graph();
int singleSize(string codeName);
int getSize();// must destroy every prerequisite list connected to the node
vertex* generateVertex(string codeName);
int getIndexOfVertex(vertex* givenVertex); // will find the location of the vertex in the array
void addVertex(vertex* newVertex);
void addEdge(string codeName, string linkCodeName);
void printPrerequisites(vertex* ptr, int i);
bool deleteVertex(string codeName);
bool deleteEdge(string codeName, string linkCodeName);
bool elemExistsInGraph(string codeName);
void printPrereq(string codeName);
void printCourseTitle(string codeName);
void printGraph();
};
I am trying to print all connected nodes within the graph using the breadth first search. Here is my code for the breadth first search algorithm that does not work.
void Graph::printPrereq(string codeName) {
int adjListSize = this->adjList.size();
int index = getIndexOfVertex(generateVertex(codeName));
bool visited[this->adjList.size()];
for(int i = 0; i < adjListSize; i++) {
visited[i] = false;
}
list<int> queue;
visited[index] = true;
queue.push_back(index);
while(!queue.empty()) {
index = queue.front();
vertex* pointer = this->adjList[index].head;
cout << pointer->code;
queue.pop_front();
while(pointer != nullptr){
if(!visited[getIndexOfVertex(pointer)]) {
queue.push_back(getIndexOfVertex(pointer));
visited[getIndexOfVertex(pointer)] = true;
}
cout << pointer->code <<"->";
pointer = pointer->next;
}
cout << "Null" << endl;
}
}
This algorithm outputs nodes that are only within the linked list, but not the ones that are connected through the graph.
Can anybody help and solve this problem?
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;
}
using namespace std;
bool *marked;
//graph API
class Digraph
{
int v;
vector<int>* adj;
int e;
public:
Digraph(int V)
{
e=0;
v=V;
adj=new vector<int>[v];
}
void addEdge(int v,int w)
{
adj[v].push_back(w);
e++;
}
int V()
{
return v;
}
vector<int> adjacent(int i)
{
return adj[i];
}
};
//API ends
//this is the problem
void dfs(Digraph g,int s)
{
marked[s]=true;
for(int w:g.adjacent(s))
{
if(!marked[w])
dfs(g,w);
}
}
The Dfs here would run perfectly when traversing nodes but when returning it would stop at one node before the last and my program halts.I compiled it on codeblocks ide.
For ex
consider a graph going 1->2->3->4->0->1
when traversing its fine but when returning will stop at vertex 3
Actually i was implementing Cycles in a graph and topological sorts too. but none of them worked, and i have no idea why.
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 have already implemented an adjacency matrix graph which uses just integers types.(consider C++ for everything that I mention here)
I'm implementing another graph that will receive cities in the vertexes and distances in the edges using my old implementation. I was wondering if this is a good idea or I should use a different implementation for this problem like linked lists. The idea here is to read all the cities and their distances to each other from a txt file, add it in the graph and then display a menu to the user so he/she can consult the distance from city A to B and get a list of all the cities he needs to travel before they reach the target.
I'm planning to read the city, give it a number code, and add it in the graph, instead of adding the string "city" (would need to convert the graph from integer to string)
What do you think,any idea/advice?
You can use either map for that. Like this
map<pair<string,string>,int> city ;
(See implementation 2)
Or you can use vector to keep track of city names with their index(implementation 1)
Implementation 1
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
class Graph
{
int V; // start vertice
map<pair<string,string>,int> city ;
vector<string> city1;
vector<string> city2;
public:
Graph(int start_V)
{
V = start_V;
}
void addEdge(string start,string end,int wt);
void display();
};
void Graph::addEdge(string start,string end,int wt)
{
city[make_pair(start,end)] = wt;
}
void Graph::display()
{
int flag=0;
for(auto it:city)
{
city1.push_back(it.first.first);
city2.push_back(it.first.second);
}
sort(city1.begin(), city1.end());
auto last = unique(city1.begin(), city1.end());
city1.erase(last, city1.end());
sort(city2.begin(), city2.end());
auto last2 = unique(city2.begin(), city2.end());
city2.erase(last2, city2.end());
for(auto col:city2)
{
cout<<"\t"<<col;
}
cout<<"\n";
for(auto row:city1)
{
int flag =0; //for printing row for once
for(auto col:city2)
{
if (!flag)
cout<<row;
cout<<"\t"<<city[make_pair(row,col)];
flag = 1;
}
cout<<"\n";
}
}
int main()
{
Graph g(2);
g.addEdge("A","B",1);
g.addEdge("C","A",5);
g.addEdge("D","E",7);
g.addEdge("E","A",5);
g.addEdge("D","B",7);
g.addEdge("D","L",7);
g.addEdge("W","L",7);
g.display();
return 0;
}
Implementation 2
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
class Graph {
int V; // start vertice
map<pair<string,string>,int> city ;
vector<string> city1;
vector<string> city2;
public:
Graph(int start_V)
{
V = start_V;
}
void addEdge(string start,string end,int wt);
void display(); }; void Graph::addEdge(string start,string end,int wt) { city[make_pair(start,end)] = wt; } void Graph::display() {
int flag=0;
for(auto it:city)
{
city1.push_back(it.first.first);
city2.push_back(it.first.second);
}
sort(city1.begin(), city1.end());
auto last = unique(city1.begin(), city1.end());
city1.erase(last, city1.end());
sort(city2.begin(), city2.end());
auto last2 = unique(city2.begin(), city2.end());
city2.erase(last2, city2.end());
for(auto col:city2)
{
cout<<"\t"<<col;
}
cout<<"\n";
for(auto row:city1)
{
int flag =0; //for printing row for once
for(auto col:city2)
{
if (!flag)
cout<<row;
cout<<"\t"<<city[make_pair(row,col)];
flag = 1;
}
cout<<"\n";
}
} int main() {
Graph g(2);
g.addEdge("A","B",1);
g.addEdge("C","A",5);
g.addEdge("D","E",7);
g.addEdge("E","A",5);
g.addEdge("D","B",7);
g.addEdge("D","L",7);
g.addEdge("W","L",7);
g.display();
return 0; }