Using BFS algorithm to find the shortest path - c++

std::list <int> q;
std::vector<bool> visited(cols + 1);
for(int i = 1; i <= cols; i++) visited[i] = false;
visited[x] = true;
if(!l[x].empty())
{
for(std::list<int>::iterator i = l[x].begin(); i != l[x].end(); i++)
{
q.push_back(x); q.push_back(* i);
}
while(!q.empty())
{
y = q.back(); q.pop_back();
x = q.back(); q.pop_back();
if(!visited[y])
{
visited[y] = true;
if(!l[y].empty())
for(std::list<int>::iterator i = l[y].begin(); i != l[y].end(); i++)
{
if(!visited[*i])
{q.push_back(y); q.push_back(* i);}
}
dfst[x].push_back(y);
if(flag != 0) dfst[y].push_back(x);
}
}
}
This is my DFS algorithm for finding the spanning tree in a graph. I need to convert it to the BFS algorithm finding the shortest path between two vertices. Well...how can I do this? Is the BFS algorithm somewhat similar to the one above? Or do I need to write it from the beginning?
l - adjacency list
dfst - array holding spanning tree at the end
x - starting vertex
y - helper variable

DFS and BFS are essentially the same algorithms. The trick is which data structure you use, or rather which nodes you are exploring first.
A depth-first search utilizes a stack and would thus go as far down as possible before moving back in the algorithm.
To utilize a breadth first search, you would need to use a queue of nodes, and explore each node, add their neighbors (if not visited already) to the queue, and then process the rest of the parent node's neighbors before continuing onwards.
It wouldn't be a drastic change of your code, just a change in how you get nodes from your list.
Rather than popping off the back you would simply use q.pop_front() to get your nodes.

BFS is similar to DFS. Instead of going as deep as you can, backtracking and repeating, you look at all nodes at depth 1, then all nodes of depth 2, etc, until you've visited all nodes.
Basic Algorithm:
-Choose a starting node and add to LookQueue
-look at all nodes directly touching and add them to LookQueue
-when you've looked at them all
-look at all nodes in LookQueue (removing them as you do)
and look at all nodes touching them (adding them as you do)
-repeat until all nodes are visited

For Finding Shortest Path
(Written in C++ / C++11)
I think this important to add here, especially because the title is on shortest paths! (the code below that actually allow you to find one)
In addition:
As mentioned above (in the comments to the second reply) DFS and BFS are pretty much not(!) the same algorithms, the similarity in the code in which replacing the stack with a queue and allowing you to jump from one to another does not make them "essentially the same". BFS is by far the better/right one (between the two) to find the shortest path in an unweighted graph. BFS is building layers from the source and DFS is going as deep as it can.
Actually when running BFS (to find the shortest path) you should initialize your nodes with a "distance" parameter with a very large number and instead using the visited DS, you update it to the parent's distance + 1 (only if it's still with the initialized value).
A simple example would be:
#include <iostream>
#include <vector>
#include <queue>
#include <limits>
using namespace std;
const int imax = std::numeric_limits<int>::max();
using vi = vector<int>;
/* printPath - implementation at the end */
void
printPath(int s, int t, const vi &path);
/*input:
* n is number of the nodes in the Graph
* adjList holds a neighbors vector for each Node
* s is the source node
*/
void dfs(int n, vector<vi> adjList, int s)
{
//imax declared above as the max value for int (in C++)
vector<int> distance(n, imax);
vi path;
queue<int> q; q.push(s); distance[s] = 0;
while (!q.empty()) {
auto curr = q.front(); q.pop();
for (int i = 0; i < (int)adjList[curr].size(); ++i) {
if (distance[i] == imax) {
distance[i] = distance[curr] + 1;
//save the parent to have the path at the end of the algo.
path[i] = curr;
}
}//for
}//while
/* t can be anything you want */
int t = 5;
printPath(s, t, path); cout << endl;
}
/* print the shortest path from s to t */
void
printPath(int s, int t, const vi &path)
{
if (t == s) {
return;
}
printPath(s, path[t], path);
cout << path[t];
}
Inspired by Steven & Felix, from:
Competitive Programming 3

No,you don't have to change much in your code. just replace replace stack in case of DFS with Queue and it will become BFS.
Difference in implementation of BFS and DFS is that "BFS is implemented using Queue and DFS is using Stack" (Reason is obvious that DFS does depth like in maze.)
SEE changes for yourself:
DFS:
void dfs(int start)
{
int j,temp;
stack<int> s; //STACK
s.push(start);
vector<int>:: iterator it;
while(s.empty()==0)
{
temp=s.top(); // Top element from Stack
s.pop();
status[temp]=1; // marked as visited , 0 means unvisited
cout<<temp<<endl; // visited element
for(it=list[temp].begin();it!=list[temp].end();it++)
{
j=*it;
if(status[j]==0)
{
s.push(j);
status[j]=2; // means that it is in stack
}
}
}
}
BFS:
void bfs(int start)
{
int j,temp;
queue<int> q; // QUEUE
q.push(start);
vector<int>:: iterator it;
while(q.empty()==0)
{
temp=q.front(); // Front element from Queue
q.pop();
status[temp]=1; // marked as visited , 0 means unvisited
cout<<temp<<endl; // visited element
for(it=list[temp].begin();it!=list[temp].end();it++)
{
j=*it;
if(status[j]==0)
{
q.push(j);
status[j]=2; // means that it is in queue
}
}
}
}
As you can see implementation of both just differ "in use of STACK and QUEUE".
Hope this helps !

Related

Change recursion to something less expensive

im trying to find the shortest path from the vertex to another. To be more precise I have a directed graph and by going always "forward" in it i will always end up in the end. Something like structure of neural network. I decided to find the shortest way with recursion which worked perfectly fine with smaller numbers. But for bigger data I get the SIGSEGV. I almost sure it's the stack overflow. Do any of you have any idea how I can switch from simple recurrence to something that wont cause the trouble?
int findShortestPath(Vertex * v, int endPointX){
if(v->isShortestPathSet())
return v->getShortestPath();
vector<int> * paths = new vector<int>;
if(v->getEndPos() == endPointX)
return 0;
for(int i = 0; i < v->getOutputEdges().size(); i ++){
Edge * outputEdge = v->getOutputEdges().at(i);
paths->push_back(findShortestPath(outputEdge->getOutputVertex(), endPointX) + outputEdge->getValue());
}
int minPath = paths->at(0);
for(int i = 0; i < paths->size(); i ++){
if(paths->at(i) < minPath)
minPath = paths->at(i);
}
v->setShortestPath(minPath);
free(paths);
return minPath;
}
this is the function with which im looking for the shortest path. It momorises the shortest possible path to each vertex so in further queries i wont have to repeat these expensive calculations.
You can implement the Dijkstra's algorithm iteratively. Here's a snippet of code which implements Dijkstra's algorithm iteratively
#include <queue>
#include <unordered_map>
#include <vector>
using IntPair = std::pair<int,int>;
std::priority_queue<IntPair, std::vector<IntPair>, std::greater<IntPair>> pq;
std::unordered_map<int, std::unordered_map<int, int>> g;
std::vector<int> distance, parent;
void dijkstras(int startVertex) {
// insert the startVertex into the priority queue(pq)
pq.push(std::make_pair(0, startVertex));
while (!pq.empty()) {
// select the vertex with least distance travelled so far from the pq
// and then, pop the selected vertex from pq
auto [dist, src] = pq.top(); pq.pop();
// iterate on all its neighbours and update distance[] and parent[]
for (auto [v, weight] : g[src]) {
if (int newDist = dist + weight; newDist < distance[v]) {
parent[v] = src;
distance[v] = newDist;
pq.push(std::make_pair(newDist, v));
}
}
}
}
Here,
pq is a priority queue which stores pairs of (distanceTravelledSoFar, previousNode). Here, pq acts as a min heap which helps us to choose the next node optimally
g is just an adjacency list that you use to stores the graph
distance is array of the shortest path distances to each of the vertex from startVertex
parent is the array which stores the previous node in the shortest path to each vertex from startVertex
Here's the link to the code which I have used to solve this question
An answer to your question is suggested in the comments (and Cherubim gives a good example of Dijkstra's algoritm.
I will also answer by modifying you code. Firstly, I think getters and setters are not necessary and you should use modern C++. Therefore I've modified your code as follows:
#include <vector>
#include <algorithm>
#include <optional>
class Vertex;
struct Edge {
Vertex* const outputVertex;
int const value;
};
struct Vertex {
int const endPoint;
std::vector<Edge const*> const outputEdges;
std::optional<int> shortestPath;
};
int findShortestPath(Vertex* const v, int endPoint){
if(v->endPoint == endPoint) return 0;
if(v->shortestPath.has_value()) return v->shortestPath.value();
auto const& outputEdges = v->outputEdges; // hopefully prevent one layer of indirection
std::vector<int> paths; paths.reserve(outputEdges.size());
std::transform(cbegin(outputEdges), cend(outputEdges), back_inserter(paths),
[endPoint] (Edge const* const outputEdge) {
return findShortestPath(outputEdge->outputVertex, endPoint) + outputEdge->value;
});
return v->shortestPath.value() = *std::min_element(cbegin(paths), cend(paths));
}
Now, to implement the stack, you have to reverse the concept you are using: instead of recursively going to the depth and returning the distance, you pass the distance forward. Together with the stack suggested in the comments, this would lead to the following code:
#include <stack>
#include <utility>
#include <climits>
int findShortestPath(Vertex const* const startVertexPtr, int endPoint) {
int minDistance = INT_MAX;
std::stack<std::pair<Vertex const*, int>> s;
s.push(std::make_pair(startVertexPtr, 0));
while(!s.empty()) {
auto [vertexPtr, distance] = s.top(); s.pop(); // structured binding
if (vertexPtr->endPoint == endPoint) {
minDistance = std::min(minDistance, distance); // end is found, see if it's path has minimum distance
continue;
}
for(Edge const* const edge : vertexPtr->outputEdges) {
s.push(std::make_pair(edge->outputVertex, distance + edge->value)); // pass the distance forward
}
}
return minDistance;
}
... but you see I'm not using Vertex::shortestPath here, which would offer an optimization. I havent' fully checked it, but you can probably do something like this:
First I again redefine Vertex
struct Vertex {
int const endPoint;
std::vector<Edge const*> const outputEdges;
int shortestPath = INT_MAX;
};
And then:
int findShortestPath(Vertex const* const startVertexPtr, int endPoint) {
int minDistance = INT_MAX;
std::stack<std::pair<Vertex const*, int>> s;
s.push(std::make_pair(startVertexPtr, 0));
while(!s.empty()) {
auto [vertexPtr, distance] = s.top(); s.pop();
if (vertexPtr->endPoint == endPoint) {
minDistance = std::min(minDistance, distance);
continue;
}
for(Edge const* const edge : vertexPtr->outputEdges) {
Vertex& vertex = *edge->outputVertex; // hopefully one less level of indirection
auto newDistance = distance + edge->value;
if (newDistance < vertex.shortestPath) {
vertex.shortestPath = newDistance;
s.push(std::make_pair(&vertex, newDistance));
}
}
}
return minDistance;
}
But there's probably more optimizations possible.

variable created on heap was not deleted in C++

I was looking into BFS search code provide in here:
// Program to print BFS traversal from a given
// source vertex. BFS(int s) traverses vertices
// reachable from s.
#include<iostream>
#include <list>
using namespace std;
// This class represents a directed graph using
// adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing adjacency
// lists
list<int> *adj;
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// prints BFS traversal from a given source s
void BFS(int s);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
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
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
// Driver program to test methods of graph class
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 Breadth First Traversal "
<< "(starting from vertex 2) \n";
g.BFS(2);
return 0;
}
In the constructor of Graph class they created a adjacency list in the heap but they never use a delete to free the memory. My question is as following
a) Is there any chance of memory leak?
If there is any memory leak how could we solve the problem?
Yes there are leaks.
Leak 1 is new list<int>[V];
Leak 2 is new bool[V];
Looks like some guy with Java or C# background wrote this piece of code. To fix the leaks use delete[] in the function void Graph::BFS(int s) also use a destructor to delete the list.
Then, you might consider std::shared_ptr.
Is there any chance of memory leak?
Yes, there is a high chance for a memory leak.
If there is any memory leak how could we solve the problem?
Generally, this can be solved by implementing a destructor. Then again, according to the rule of three, we would need a copy-constructor as well, just in case an end user decides to copy one list to another.
But we could actually sidestep this by not dynamically-allocating in the first place! Let's reimplement with std::vector:
class Graph
{
int V;
vector<list<int>> adj;
public:
Graph(int V);
// ...
};
Graph::Graph(int V)
{
this->V = V;
adj.assign(V, list<int>()); // std::vector::assign
}
void Graph::BFS(int s)
{
// Mark all the vertices as not visited
vector<bool> visited(V); // see note below *
for(int i = 0; i < V; i++)
visited[i] = false;
// Create a queue for BFS
list<int> queue;
// Mark the current node as visited and enqueue it
visited[s] = true;
queue.push_back(s);
// 'i' will be used to get all adjacent
// vertices of a vertex
list<int>::iterator i;
while(!queue.empty())
{
// Dequeue a vertex from queue and print it
s = queue.front();
cout << s << " ";
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
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}
There are a ton of other minor issues with this code, but I shall leave that as an exercise for the reader.
*Note: vector<bool> isn't your normal vector.

Creating a graph with c++ based on user input

I am trying to modify the DFS algorithm in C++ from the geeks4geeks site so that the graph is created according to users input.
Original code:
// C++ program to print DFS traversal from
// a given vertex in a given graph
#include<iostream>
#include<list>
using namespace std;
// Graph class represents a directed graph
// using adjacency list representation
class Graph
{
int V; // No. of vertices
// Pointer to an array containing
// adjacency lists
list<int> *adj;
// A recursive function used by DFS
void DFSUtil(int v, bool visited[]);
public:
Graph(int V); // Constructor
// function to add an edge to graph
void addEdge(int v, int w);
// DFS traversal of the vertices
// reachable from v
void DFS(int v);
};
Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}
void Graph::addEdge(int v, int w)
{
adj[v].push_back(w); // Add w to v’s list.
}
void Graph::DFSUtil(int v, bool visited[])
{
// Mark the current node as visited and
// print it
visited[v] = true;
cout << v << " ";
// Recur for all the vertices adjacent
// to this vertex
list<int>::iterator i;
for (i = adj[v].begin(); i != adj[v].end(); ++i)
if (!visited[*i])
DFSUtil(*i, visited);
}
// DFS traversal of the vertices reachable from v.
// It uses recursive DFSUtil()
void Graph::DFS(int v)
{
// Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i = 0; i < V; i++)
visited[i] = false;
// Call the recursive helper function
// to print DFS traversal
DFSUtil(v, 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;
}
I've changed the main() function to read from cin as follows, leaving the remaining part of the code the same:
int main()
{
int V,A[4][2];
cin>>V;
Graph g(V);
for(int i=0;i<V;i++){
cin>> A[i][0];
cin>>A[i][1];
}
for (int j=0;j<V;j++){
g.addEdge(A[j][0], A[j][1]);
}
g.DFS(2);
return 0;
}
The graph is given in adjacency list, for example with the following input data (first line is the V parameter, remaining lines represent edges from one node to another):
4
1 2
2 3
3 1
4 2
4 1
These are stored in the array sequentially, so once the data is read, I expect that:
A[0][0]=1, A[0][1]=2 (edge 1->2)
A[1][0]=2, A[1][1]=3 (edge 2->3)
...
But the output of the IDE is:
Command terminated by signal 11.
I think this is a segmentation fault and it means that I am trying to access memory I should not but I don't know how to fix this. Any ideas?
The problem with your reading function is that you can read only one edge per node. So a part of the edges is ignored. Consider this refactoring:
int main()
{
int V,A[2];
cin>>V;
Graph g(V);
while ( cin>> A[0]>>A[1] ) {
if (A[0]<0 || A[1]<0 || A[0]>=V || A[1]>=V)
cout << A[0]<<"->"<<A[1]<<" refers to a non-existent node"<<endl;
else g.addEdge(A[0], A[1]);
}
g.DFS(2);
return 0;
}
As you see, I've added a validation on the data read in order to avoid obvious errors. Running it on your test data will show you that there's a problem with your node identifications: you go from 1 to 4 in the test data, while your code expects from 0 to 3 (because the graph is implemented as an array of V adjacency lists and you shall not go out of range).
Here an online demo.

How to do InOrder traversal with B-Tree?

struct BTreeNode {
bool is_leaf=true;
std::vector<int> elements;
std::vector<BTreeNode*> children;
BTreeNode() {}
BTreeNode (std::vector<int> v) {
this->elements = v;
}
};
void traverse(BTreeNode* root) {
for(int i = 0; i < (int)root->children.size(); ++i){
traverse(root->children[i]);
cout << root->elements[i] << endl;
}
traverse(root->children[root->children.size() -1]);
}
My method somehow segfaults. How do we write a correct inOrder Traversal for B-Tree?
It's probably the last traverse call when you are at a leaf. I don't think that this traverse is needed.
Assuming BTreeNode is a generic definition of your b-tree node, whereas T1 is the type of the keys and T2 is the type of the values in the tree, and sortedKeys is the list you are after, you can use the following recursive method. The idea is very similar to an inOrder traversal in binary search tree, first visit the left-most child, then visit the key- then continue, Since the number of children in B-tree is always one bigger than the number of keys, a check is needed before visiting the key [code is in c#, but can easily be converted to any other language, the purpose is to show the algorithm only].
public void InOrderTraversal(BTreeNode<T1, T2> node, List<KeyValuePair<T1, T2>> sortedKeys)
{
if (node != null)
{
for (int i = 0; i < node.Children.Count; i++)
{
InOrderTraversal(node.Children[i], sortedKeys);
if (i < node.KeyValues.Count)
sortedKeys.Add(node.KeyValues[i]);
}
}
}

Detecting cycle in an undirected graph using iterative DFS?

So, I implemented the DFS in an iterative manner by the following method:
void dfsiter (graph * mygraph, int foo, bool arr[])
{
stack <int> mystack;
mystack.push(foo);
while (mystack.empty() == false)
{
int k = mystack.top();
mystack.pop();
if (arr[k] == false)
{
cout<<k<<"\t";
arr[k] = true;
auto it = mygraph->edges[k].begin();
while (it != mygraph->edges[k].end())
{
if (arr[*it] == false)
{
mystack.push(*it);
}
it++;
}
}
}
}
The above code works completely fine. Now, I want to detect cycles in an undirected graph using the above code (Iterative DFS). Now, I read that, If an unexplored edge leads to a node visited before, then the graph contains a cycle. Therefore, I just want to ask you, how do I exactly keep track of all this?
I have taken my graph to be like this:
class graph
{
public:
int vertices;
vector < vector<int> > edges;
};
Should I change the above to:
class graph
{
public:
int vertices;
vector < vector<pair<int,bool> > edges;
};
Where the bool for each edge will be marked true? And what changes will I need to do in the above code for DFS for detecting the cycle? I tried but I couldn't really think of a way of doing it. Thanks!
You can store a "father" node f in DFS tree for each vertex v, i.e. the vertex from which DFS came to the vertex v. It can be stored in the stack for example. In this case you store pairs in stack, first value is the vertex v and the second one is its father f.
An undirected graph has a cycle if and only if you meet an edge vw going to already visited vertex w, which is not the father of v.
You can see the modified and cleaned code below.
bool hascycle (graph * mygraph, int start, bool visited[])
{
stack <pair<int, int> > mystack;
mystack.push(make_pair(start, -1));
visited[start] = true;
while (!mystack.empty())
{
int v = mystack.top().first;
int f = mystack.top().second;
mystack.pop();
const auto &edges = mygraph->edges[v];
for (auto it = edges.begin(); it != edges.end(); it++)
{
int w = *it;
if (!visited[w])
{
mystack.push(make_pair(w, v));
visited[w] = true;
}
else if (w != f)
return true;
}
}
return false;
}
Note: if the graph is disconnected, then you must start DFS from several vertices, ensuring that the whole graph is visited. It can be done in O(V + E) total time.