Adjacency List in graph - c++

Hi I am try to implement a graph using adjacency list using following code.
#include<iostream>
#include<list>
#include<vector>
#include<unordered_map>
using namespace std;
class graph{
public:
vector<int> adj[10000];
void insert(int u,int v, bool direction) {
adj[u].push_back(v);
if(direction==1) {
adj[v].push_back(u);
}
}
void print(int n) {
for(int i=0;i<n+1;i++) {
cout<<i<<"->";
for(auto j : adj[i]) {
cout<<j<<",";
}
cout<<endl;
}
}
};
int main( ) {
int n;
cout<<"Enter no of node"<<endl;
cin>>n;
cout<<"enter edges "<<endl;
int m;
cin>>m;
graph g;
for(int i=0;i<m;i++) {
int u, v;
cin>>u>>v;
g.insert(u,v,1);
}
g.print(n);
return 0;
}
But the problem with this code is that it will give correct answer only in the case when my node start from 0 in a continuous manner(0,1,2,3). But when I try to print adjacency list of this graph:
Then it is giving this output:
Can somebody tell me where am I wrong?

The edges you are adding aren't the same as the graph i picture, you are inputting edge 1, 3 instead of edge 1, 5.

It's printing the 0 because you started that for loop from i = 0 and it doesn't print node 5 for the same reason (the loop ends at 4 because you will have i < 4 + 1.
void print(int n) {
//↓↓↓ HERE
for(int i=0;i<n+1;i++) {
cout<<i<<"->";
for(auto j : adj[i]) {
cout<<j<<",";
}
cout<<endl;
}
}
Here is how I would change your code:
First, I changed the print() function a little (added the if() to see if the current row is empty and I changed the int n parameter to int maximum which will hold the highest value node so we know when to stop the for).
void print(int maximum)
{
for(int i=0; i<=maximum; i++)
{
if(!adj[i].empty())
{
cout<<i<<"->";
for(auto j : adj[i])
{
cout<<j<<",";
}
cout<<endl;
}
}
}
Then, in main() I added the maximum and aux variables in order to store the aforementioned highest value node. And I also changed the g.print(n) to g.print(maximum).
int main( )
{
int n, maximum = 0, aux;
cout<<"Enter no of node"<<endl;
cin>>n;
cout<<"enter edges "<<endl;
int m;
cin>>m;
graph g;
for(int i=0; i<m; i++)
{
int u, v;
cin>>u>>v;
g.insert(u,v,1);
aux = max(u, v);
maximum = max(maximum, aux);
}
g.print(maximum);
return 0;
}
However, I might not be Terry A. Davis, but I know that if you say you have 4 nodes, those 4 nodes will be 1 2 3 and 4. And I also know that any graph related problem will have nodes starting from 1, therefore every for loop would start from i = 1, or at least that's how I was taught. The way you did it might be correct too, but I am not sure.

Related

Memory leak in Depth First Search Algorithm on Graphs

I was doing a course on Coursera where they asked to implement DFS to see if two vertices of a graph are connected. I came up with the code and it gives the correct output on my laptop but it gives incorrect output on their grader. I've been breaking my head for days on this problem and have absolutely no idea where I've gone wrong. The code is as follows:
#include<iostream>
#include<vector>
using namespace std;
class Graph
{
public:
vector<int> adj; //adjacency list
void add(int a)
{
adj.push_back(a);
}
void DFS(bool visited[],int n,Graph G[],int v)
{
for(int i=0;i<G[v].adj.size();i++)
{
int vert=G[v].adj[i];
if(visited[vert]==false)
{
visited[vert]=true;
DFS(visited,n,G,vert);
}
}
}
};
int main()
{
int n,m;
cin>>n>>m;//No. of vertices,number of edges
bool visited[n];
for(int i=0;i<n;i++)
visited[n]=false;
Graph G[n];
for(int i=0;i<m;i++)
{
int u,v;
cin>>u>>v; //The vertices joined by two edges
G[u-1].add(v-1);
G[v-1].add(u-1);
}
int k,l;
cin>>k>>l; //The vertices to be checked if they are connected
G[k-1].DFS(visited,n,G,k-1);
if(visited[l-1]==true)
cout<<1;
else
cout<<0;
}
Grader Output:
Failed case #2/16: (Wrong answer)
Input:
4 2
1 2
3 2
1 4
Your output:
1
Correct output:
0
(Time used: 0.00/1.00, memory used: 7839744/536870912.)
If I run the above case in my laptop, it gives the output as 0, the expected answer. I asked the question on the forum and they say that there is some memory leak which I can't identify. Please help.
If you're writing a Graph class, then you should really encapsulate all functionality inside that class. You're not supposed to overwhelm the main function. It makes your code convoluted. Plus you don't have to pass around a lot things in case of a function call. Avoid using using namespace std; as it will lead to namespace collision. To avoid writing std::cout or std::cin, consider using std::cout and using std::cin. I refactored your code and now it gives correct output:
#include <iostream>
#include <cstring>
#include <vector>
using std::cout;
using std::cin;
class Graph
{
public:
static constexpr int MAXN = 100;
std::vector <int> adj[MAXN + 1]; //adjacency list
int visited[Graph::MAXN + 1]; // for 1 based indexing
Graph(){
for(int i = 0 ; i <= MAXN ; ++i) adj[i].clear();
memset(visited, 0, sizeof(visited));
}
void addEdge(bool isDirected, int u, int v)
{
adj[u].push_back(v);
if(!isDirected) adj[v].push_back(u);
}
void takeInput(bool isDirected, int nodes, int edges){
for(int i = 0 ; i < edges ; i++){
int u,v; cin >> u >> v;
addEdge(isDirected, u, v);
}
}
void DFS(int source)
{
visited[source] = 1;
for(int i = 0 ; i < adj[source].size() ; ++i){
int adjNode = adj[source][i];
if(visited[adjNode] == 0){
DFS(adjNode);
}
}
}
bool isConnected(int source, int destination){
DFS(source - 1);
return visited[destination - 1];
}
};
int main()
{
int nodes, edges;
cin >> nodes >> edges;//No. of vertices,number of edges
Graph g;
g.takeInput(false, nodes, edges);
int source, destination;
cin >> source >> destination; //The vertices to be checked if they are connected
cout << g.isConnected(source, destination) << '\n';
return 0;
}

Get path between 2 vertices using BFS in C++

I have written a code for this but it gives segmentation fault for disconnected graphs. It works fine for graphs that are connected.
How can I overcome this error?
vector<int> getPathBFS(int V, int** edges,int v1, int v2, int* visited, unordered_map<int,int> t)
{
queue<int> q;
q.push(v1);
visited[v1]=1;
int done=0;
while(!q.empty() && done==0)
{
for(int i=0;i<V;i++)
{
int front=q.front();
q.pop();
if(edges[front][i]==1 && visited[i]!=1)
{
q.push(i);
t[i]=front;
visited[i]=1;
if(i==v2)
{
done=1;
break;
}
}
}
}
vector<int> a;
if(done==0)
return a;
else
{
int k=v2;
a.push_back(v2);
while(k!=v1)
{
k=t[k];
a.push_back(k);
}
return a;
}
}
int main()
{
int V, E;
cin >> V >> E;
int** edges=new int*[V];
for(int i=0;i<V;i++)
{
edges[i]=new int[V];
for(int j=0;j<V;j++)
{
edges[i][j]=0;
}
}
for(int i=0;i<E;i++)
{
int f,s;
cin>>f>>s;
edges[f][s]=1;
edges[s][f]=1;
}
int v1,v2;
cin>>v1>>v2;
int* visited=new int[V];
for(int i=0;i<V;i++)
visited[i]=0;
unordered_map<int,int> t;
t[v2]=0;
vector<int> ans=getPathBFS(V,edges,v1,v2,visited,t);
for(int i=0;i<ans.size();i++ && !ans.empty())
{
cout<<ans[i]<<" ";
}
delete [] visited;
for(int i=0;i<V;i++)
{
delete [] edges[i];
}
delete [] edges;
return 0;
}
I did a dry run of the code. It will first create adjacency matrix edges and mark all the edges in it. Visited array is used to keep track of all the vertices that have been visited till now so that there is no infinite loop.
For the test case given below it will work till the queue contains 1 then it will pop 1 and the loop will end because there is no edge left that is connected to 1 and is not visited. After this the while loop should ideally break and as done==0 it should return an empty vector. I can't understand why the segmentation fault is coming.
The map is being used to keep track of which vertex was put in the queue by which vertex.
Doesn't work for the test case:
6 3
5 3
0 1
3 4
0 3
Below is the image of the graph for the above test case:
Here we need to find the path from vertex 0 to 3.
The input format is :
Number of Vertices in the graph, Number of edges
Edges between the vertices (for E lines),
Vertices between which we need to find the path.
You are popping the BFS queue incorrectly. Instead of the inner for loop, which is executed |V| times for each entry in the queue, you should pop the queue in the outer loop, which is executed once for each element in the queue.
vector<int> getPathBFS(int V, int** edges,int v1, int v2, int* visited, unordered_map<int,int> t)
{
queue<int> q;
q.push(v1);
visited[v1]=1;
int done=0;
while(!q.empty() && done==0)
{
int front=q.front();
q.pop();
for(int i=0;i<V;i++)
{
if(edges[front][i]==1 && visited[i]!=1)
{
q.push(i);
t[i]=front;
visited[i]=1;
if(i==v2)
{
done=1;
break;
}
}
}
}
vector<int> a;
if(done==0)
return a;
else
{
int k=v2;
a.push_back(v2);
while(k!=v1)
{
k=t[k];
a.push_back(k);
}
return a;
}
}
Also, in main function of your code, there is a redundant expression !ans.empty() in the for loop where you are printing the answer(s).

My code runs fine when I debug it, but crashes as soon as I run it

I have been asked to built a K sorted array by my professor and then sort it using minheap. A k sorted array is basically an array where each element is at most K positions away from the location it would be if the array was fully sorted in ascending order. For instance, if K=3, the element at position i=8 can be at locations 5, 6, 7, 8, 9, 10, or 11 in the fully sorted arrayI'm stuck in the first part of the problem.
Requirements:
Allow the user to enter a number of (N) elements and the number K.
Produce a K-sorted array based on the user input (more than one K-sorted array can be produced; randomly pick one). Display it.
After rigorous thinking I built the below code for K Sorting:
void kSortedArray:: displayKSorted()
{
cout<<"Please enter the no. of elements you want to KSort: ";
cin>>N;
cout<<"Please enter the value for K: ";
cin>>K;
int i=0;
while (i<N)
{
cout<<"Enter element "<<i+1<<" : ";
cin>>arr[i++];
}
insertion_sort(arr,N);
srand(time(NULL));
int output=0;
i=0;
int maxRand=0;
int minRand=0;
int arr2[N];
int a=0;
int found=0;
int found1=0;
int range=0;
int count1=0;
vector<int>:: iterator it1;
vector<int>:: iterator it2;
vector<int> arr3;
while(kSortedIndex.size()<N)
{
minRand=range-K;
maxRand=range+K;
output = minRand + (rand() % (maxRand - minRand + 1));
if (output<0)
{
output=N+output;
}
if(output>N-1)
{
output=output-N;
}
//arr2[i]=output;
for(it1=kSortedIndex.begin();it1!=kSortedIndex.end();it1++)
{
if(*it1==output)
{
found=1;
for(it2=arr3.begin();it2!=arr3.end();it2++)
{
if(*it2==output)
{
found1=1;
break;
}
}
if(found1==0)
{
arr3.push_back(output);
count1++;
}
break;
}
}
if(found==0)
{
kSortedIndex.push_back(output);
count1=0;
arr3.clear();
range++;
}
found=0;
found1=0;
if (count1>((2*K)+1))
{
range--;
count1=0;
}
if(range>(N-1))
range--;
}
vector<int>::iterator it;
int j=0;
// i=0;
for(it=kSortedIndex.begin();it!=kSortedIndex.end();it++)
{
arr2[*it]=arr[j];
j++;
//cout<<arr2[j++];
}
for(j=0;j<N;j++)
{
cout<<arr2[j];
}
}
Below is the header file:
class kSortedArray
{
public:
kSortedArray();
void displayKSorted();
protected:
private:
int N=0;
int K=0;
int* arr=new int [N];
createKSorted();
void insertion_sort(int arr[],int length);
vector <int> kSortedIndex;
};
Could someone please help me to figure out why my code crashes when I run it and runs fine when I debug it. Is it a memory leak issue? I even tried deleting arr, arr2 and clearing arr3 but that isn't working (code still cashes). Your help much appreciated.
The declaration int* arr=new int [N]; in the header is wrong. You cannot allocate memory for the array here because you do not yet know the value for N. That value will be known only after cin>>N; in the kSortedArray:: displayKSorted function. Therefore you need to do allocate memory there:
void kSortedArray:: displayKSorted()
{
cout<<"Please enter the no. of elements you want to KSort: ";
cin>>N;
arr = new int [N]; // <<< add this line
cout<<"Please enter the value for K: ";
cin>>K;
int i=0;
...
Header:
...
private:
int N=0;
int K=0;
int* arr; // =new int [N]; <<< remove the allocation
createKSorted();
void insertion_sort(int arr[],int length);
...
Disclaimer: This is non tested non error checking code, and there may be more problems.

I am trying to run the following code for quicksort but the output is always a garbage value.What should be the modification in the code?

this is the following code
#include<iostream>
using namespace std;
int findPivot(int a[],int startIndex,int endIndex)
{
int pivot=a[endIndex];
int pivotIndex=startIndex;
for(int i=0;i<endIndex-1;i++)
{
if(a[i]<pivot)
{
int temp=a[i];
a[i]=a[pivotIndex];
a[pivotIndex]=a[i];
pivotIndex++;
}
}
int temp=pivot;//swapping pivot element into its position.
pivot=a[pivotIndex];
a[pivotIndex]=temp;
return pivotIndex;
}
void quickSort(int a[],int startingIndex,int endingIndex)
{
int number;
if(startingIndex < endingIndex)
{
int returnValueOfPivot= findPivot(a,startingIndex,endingIndex);
//cout<<returnValueOfPivot<<endl;
quickSort(a,startingIndex,returnValueOfPivot-1);//sorting for left
quickSort(a,returnValueOfPivot+1,endingIndex);//sorting for right
}
}
int main()
{
int number;
cout<<"Enter the total number of elements"<<endl;
cin>>number;
cout<<"Enter the values"<<endl;
int a[number-1];
for(int i=0;i<number;i++)
{
cin>>a[i];
}
quickSort(a,0,number-1);
for(int i=0;i<number;i++)
{
cout<<a[i]<<",";
}
return 1;
}
There are three major problems in your code :
int a[number-1];
You are allocating 1 less space for your array. Note that, array index starts from 0. So array of 5 numbers will be like
array[5] : array[0],array[1],array[2],array[3],array[4]
Swapping array values :
int temp=pivot;//swapping pivot element into its position.
pivot=a[pivotIndex];
a[pivotIndex]=temp;
Here, you swapped pivot value with a[pivotIndex] not a[endIndex]!!
So the correct swap would have been :
int temp=a[endIndex];//swapping pivot element into its position.
a[endIndex]=a[pivotIndex];
a[pivotIndex]=temp;
for(int i=0;i<endIndex-1;i++) is incorrect loop
correct loop would be :
for(int i=startIndex;i<=endIndex-1;i++)
You need to start from the start index and end till the end index. You are currently going from 0 to end - 1. [Think of the right side array loop, it won't start with 0]
Make these changes and your code will work.

Segmentation fault in c++ program for dijkstra's algorithm

This is my code.. I tried hard to detect the fault but it compiles properly and then gives segmentation fault while executing...
#include<iostream>
#include<string>
using namespace std;
#define infinity 999
#define MAX 10
int min(int dis[],bool vis[],int n);
void print_dij(int dis[],int n);
class graph
{
int g[MAX][MAX];
public:
int n;
graph()
{
n=0;
}
void readgraph();
void printgraph();
void dij();
};
void graph::readgraph()
{
int i,j;
cout<<"\nEnter the no of vertices::";
cin>>n;
cout<<"\nEnter the adjacency matrix::";
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
cout<<"\n["<<i<<"]["<<j<<"]::";
cin>>g[i][j];
}
}
}
void graph::printgraph()
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<g[i][j];
cout<<"\n";
}
}
void graph::dij()
{
int dis[20],i,j,start,u;
bool vis[20];
cout<<"\nEnter the index number of starting node::";
cin>>start;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
if(g[i][j]==0)
g[i][j]=infinity;
for(i=0;i<n;i++) //Initialising the arrays dis[] and vis[]
{
dis[i]=infinity;
vis[i]=false;
}
dis[start]=0;
for(i=0;i<n-1;i++) //Finding the shortest path
{
u=min(dis,vis,n);
vis[u]=true;
for(j=0;j<n;j++)
if(!vis[j] && g[u][j] && dis[u]!=infinity && dis[u]+g[u][j]<dis[j])
dis[i]=dis[u]+g[u][j];
}
cout<<"\nThe shortest path is::->>>>>\n";
print_dij(dis,n);
}
int min(int dis[],bool vis[],int n) //To find the vertex with min distance from the source
{
int index,i,min=infinity;
for(i=0;i<n;i++)
if(vis[i]=false && dis[i]<=min)
{
min=dis[i];
index=i;
}
return index;
}
void print_dij(int dis[],int n) //To print the shortest path
{
int i;
cout<<"\nVertices\tMinimum distance";
for(i=0;i<n;i++)
{
cout<<"\n"<<i<<"\t"<<dis[i];
}
}
int main()
{
graph g;
int start;
g.readgraph();
cout<<"\nThe entered graph is::\n";
g.printgraph();
g.dij();
return 0;
}
It seems like the fault is in the loop for finding the shortest path in the dij() function. But still i am not able to figure out the problem. Please help me out... :-|
Seems like you have many problem of initialization but with this change your said error would go.
In function int min(int dis[],bool vis[],int n) initialize index to zero.
int index=0
Just a quick question: in min(...) the n is which n? n is graph::n or n from the parameter list?