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.
Related
I was trying to implement BFS in C++, the function should work like this: takes a graph & a vertex as parameters, then create two vectors, one of these is used to store the vertices adjacent with the parameter vertex, then check those vertices, if one of them is unvisited, then get it's adjacencies and add them to vector, after that the vertex should be marked as VISITED and printed; I wrote this code but it did output anything. NOTE: I ensured that the other functions & data structures like the graph are working, the problem is in the BFS function, I hope some of you can help me to fix it.
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
enum Mark {VISITED, UNVISITED};
struct Vertex {
char name;
Mark mark;
};
struct Edge{
Vertex v1;
Vertex v2;
Edge(Vertex vertex1, Vertex vertex2): v1(vertex1), v2(vertex2){};
};
struct Graph{
vector<Vertex>vertices;
vector<Edge>edges;
vector<pair<Vertex, Edge>> adjacent(char u){
vector<pair<Vertex, Edge>>res;
for(Edge e : edges){
if(e.v1.name == u){
res.push_back(make_pair(e.v2, e));
}else if(e.v2.name == u){
res.push_back(make_pair(e.v1, e));
}
}
return res;
}
vector<Vertex> getAdj(char u){
vector<Vertex>result;
for(Edge e: edges){
if(e.v1.name == u){
result.push_back(e.v2);
}else if(e.v2.name == u){
result.push_back(e.v1);
}
}
return result;
}
};
void BFS(Graph g, Vertex u){
vector<Vertex>vec = g.getAdj(u.name);
for(Vertex v : vec){
if(v.mark == UNVISITED){
vector<Vertex>q = g.getAdj(v.name);
for(int i=0; i<q.size(); i++){
vec.push_back(q[i]);
}
v.mark = VISITED;
vec.pop_back();
cout << v.name << " ";
}
}
}
int main(int argc, const char * argv[]) {
Graph g;
Vertex v1, v2, v3, v4, v5, v6;
v1.name = 'A';
v2.name = 'B';
v3.name = 'C';
v4.name = 'D';
v5.name = 'E';
v6.name = 'Z';
g.edges.push_back(Edge(v1, v2));
g.edges.push_back(Edge(v1, v3));
g.edges.push_back(Edge(v2, v3));
g.edges.push_back(Edge(v2, v4));
g.edges.push_back(Edge(v3, v4));
g.edges.push_back(Edge(v3, v5));
g.edges.push_back(Edge(v4, v5));
g.edges.push_back(Edge(v4, v6));
g.edges.push_back(Edge(v5, v6));
BFS(g, v1);
cout << endl;
}
You're not fully initialising your Vertexs. You give them names, but not the initial mark tag.
You can add this in your main:
v1.mark = UNVISITED;
v2.mark = UNVISITED;
v3.mark = UNVISITED;
v4.mark = UNVISITED;
v5.mark = UNVISITED;
v6.mark = UNVISITED;
You can also do something like this (might be better to replace with enum class):
enum Mark {VISITED, UNVISITED};
struct Vertex {
char name;
Mark mark = UNVISITED;
};
(I would also create a constructor to initialise the names to make sure you're not forgetting to do that).
UPDATE:
There are several problems with your BFS:
- Since you're adding elements to vec inside your inner loop, the outer loop isn't working properly (I think it has to do with iterators and happens because you change the size of the vector all the time). I managed to solve it using a regular for loop.
even if you managed to use a ranged for-loop, you're going from "left to right" in the vector. And you're using pop_back() which removes from the end of a vector (so at the rightmost of the vector). I don't think this is what you want.
You have the right idea by marking eacher Vertex as visited and not visited. But you're only updating the Vertexs in vec which are in the BFS function. But they are only copies from the getADj method, which means each time you add the new neighbors to your vec, anytime there are vertices you already visited, that value is not known. Effectively you're adding a new Vertex which is never visited.
There might be other issues, but already with those ones you should have plenty on your hands!
I'd recommend you use a debugger and/or a tool like 'valgrind', to help find problems in your code.
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.
I have a set of edges E, and I want to know if I can safely remove edge i in E, meaning if I remove it from the graph, the graph should still be connected.
In my understanding that implies that edge i, has to lie on a circle.
The output should be a list of indices of all edges I can't remove.
The problem:
My different solutions seem to do the right thing, but are far too slow (inefficient).
One of my solutions was:
1. Loop through all edges i in E
2. Loop through all edges x in V
3. Add edge x to the graph (excluding edge i) until nodes of i are connected or end reached
4. If no connection possible, edge is not removable and added to the list
This way was way too slow.
I then decided to rewrite my code and use breadth-first-search to look if another path is possible without edge i.
I thought it would be performant enough, but it seems it's not. Either I have implemented in a very bad way or that's also the wrong algorithm for this task.
Here is the algorithm in the C++ code I have (removed some not important parts):
struct connection {
int a, b;
};
void expand(int x, connection *&arr, std::set<int> &exp, int size) {
for (int i = 0; i < size; i++) {
if (x == arr[i].a) {
exp.insert(arr[i].b);
}
else if (x == arr[i].b) {
exp.insert(arr[i].a);
}
}
return;
}
// recursive breadth-first-seach
bool BFSr(std::set<int> &group, std::set<int> &visited, int goal, connection *&arr, int size) {
if (group.empty()) return false;
if (group.find(goal) != group.end()) return true;
std::set<int> tempa;
for (std::set<int>::iterator it = group.begin(); it != group.end(); ++it) {
expand(*it, arr, tempa size);
}
for (std::set<int>::iterator it = visited.begin(); it != visited.end(); ++it) {
tempa.erase(*it);
}
tempb = visited;
tempb.insert(group.begin(), group.end());
return BFSr(tempa, tempb, goal, arr, size);
}
bool BFS(int start, int goal, connection *&arr, int size) {
std::set<int> tempa;
std::set<int> tempb;
tempa.insert(start);
return BFSr(tempa, tempb, goal, arr, size);
}
int main()
{
connection *arr = new connection[m];
connection *con = new connection[m - 1];
// fill arr with connections arr.a < arr.b ....
for (int j = 0; j < (m - 1); j++) {
con[j] = arr[j + 1];
}
// 1. edge for performance reasons extra
if (!BFS(arr[0].a, arr[0].b, con, (m - 1))) {
// connection is important therefore add to list
printf(" %d", 1);
}
// Look if nodes still connected after removing connection
for (int s = 1; s < m; s++) {
con[s - 1] = arr[s - 1];
if (!BFS(arr[s].a, arr[s].b, con, (m-1))) {
// connection is important therefore add to list
printf(" %d", s + 1);
}
}
printf("\n");
free(arr);
free(con);
return 0;
}
Do you know any solutions for me to make it faster, or do you know a better algorithm for my problem?
An edge whose deletion disconnects two connected components is called a bridge and there are linear-time algorithms for finding all the bridges in a graph (usually based on depth-first search). The Wikipedia article lists one of them (due to Tarjan) as an example. This paper also gives a simple algorithm for listing all the bridges in a graph and seems to be a bit simpler than Tarjan's algorithm.
Hope this helps!
Here is another version of your algorithm (I guess you will get industry standard optimization implementation of graph and various algorithm for free):
I am referring to this image as graph model.
Gist (from this post)
find articulation points
all points with single out-edge are
articulation points (boost graph won't return these)- these edges
are automatically bridging edges
for each articulation point-
loop over each outedge, if outedge already not bridging edge- then
remove the edge and check for graph components and add the edge back
again
At the end it will print Edge(a,g) connects components in graph
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/biconnected_components.hpp>
#include <boost/graph/connected_components.hpp>
#include <functional>
#include <string>
#include <vector>
#include <unordered_map>
#include <unordered_set>
typedef boost::adjacency_list <boost::vecS, boost::vecS, boost::undirectedS> Graph;
typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t;
typedef boost::graph_traits<Graph>::edge_descriptor edge_t;
// reference:
// http://lists.boost.org/boost-users/2005/08/13098.php
//
struct edge_t_hasher
{
std::size_t operator()(const edge_t& e) const
{
auto prop = e.get_property();
std::hash<decltype(prop)> hasher;
return hasher(prop);
}
};
typedef std::unordered_set<edge_t, edge_t_hasher> UnorderedBoostEdgeSet;
Graph getGraph()
{
Graph g;
vertex_t aVtx = boost::add_vertex(g);
vertex_t bVtx = boost::add_vertex(g);
vertex_t cVtx = boost::add_vertex(g);
vertex_t dVtx = boost::add_vertex(g);
vertex_t eVtx = boost::add_vertex(g);
vertex_t fVtx = boost::add_vertex(g);
vertex_t gVtx = boost::add_vertex(g);
vertex_t hVtx = boost::add_vertex(g);
vertex_t iVtx = boost::add_vertex(g);
boost::add_edge(dVtx, cVtx, g);
boost::add_edge(dVtx, bVtx, g);
boost::add_edge(cVtx, bVtx, g);
boost::add_edge(aVtx, bVtx, g);
boost::add_edge(bVtx, eVtx, g);
boost::add_edge(eVtx, fVtx, g);
boost::add_edge(aVtx, fVtx, g);
boost::add_edge(aVtx, gVtx, g);// edge connecting components
boost::add_edge(gVtx, iVtx, g);
boost::add_edge(gVtx, hVtx, g);
boost::add_edge(hVtx, iVtx, g);
return g;
}
UnorderedBoostEdgeSet bridgingEdgesForGraph(const Graph& graph)
{
UnorderedBoostEdgeSet bridgeEdges;
std::unordered_set<vertex_t> articulationVertices;
boost::articulation_points(graph, std::inserter(articulationVertices, articulationVertices.end()));
// add all the single connected vertices to the articulation vertices
auto vtxIters = boost::vertices(graph);
for (auto it = vtxIters.first, end = vtxIters.second; it != end; ++it)
{
if (boost::out_degree(*it, graph) == 1)
bridgeEdges.insert(*(boost::out_edges(*it, graph).first));
}
std::vector<vertex_t> componentsInGraph(boost::num_vertices(graph));
int numComponentsInGraph = boost::connected_components(graph, &componentsInGraph[0]);
// for each articulation vertex now get edges and check if removing that
// edge causes graph change in connected components
//
// copy the graph- so we can iterate over the outeges of vertices
// we will be fiddling with the copy- since the vtx descriptors are
// ints- they stay same across copy and removing edge operation
auto graph2 = graph;
for (auto vtx : articulationVertices)
{
auto outEdges = boost::out_edges(vtx, graph);
for (auto it = outEdges.first, end = outEdges.second; it != end; ++it)
{
auto edge = *it;
if (bridgeEdges.find(edge) != bridgeEdges.end())
continue;
// map this edge to graph2 edge- for removal and eventual addition
auto src = boost::source(edge, graph);
auto tgt = boost::target(edge, graph);
auto edge2 = boost::edge(src, tgt, graph2).first;
boost::remove_edge(edge2, graph2);
std::vector<vertex_t> componentsInGraph2(boost::num_vertices(graph2));
int numComponentsInGraph2 = boost::connected_components(graph2, &componentsInGraph2[0]);
// bridging edge- graph #components changed
if (numComponentsInGraph != numComponentsInGraph2)
bridgeEdges.insert(edge);
// add the edge back to graph2
boost::add_edge(src, tgt, graph2);
}
}
return bridgeEdges;
}
int main()
{
const Graph& graph = getGraph();
const auto& bridgingEdges = bridgingEdgesForGraph(graph);
const char* array = {"ABCDEFGHI"};
for (auto edge : bridgingEdges)
{
std::cout << "Edge(" << array[boost::source(edge, graph)] << ", " << array[boost::target(edge, graph)]
<< ") is a bridging edge" << std::endl;
}
return 0;
}
Meanwhile I found out how those special edges are called: Bridges.
And therefore I found a site giving an DFS algorithm for finding all bridges.
It's fast enough for my purposes.
DFS algorithm for finding Bridges in a undirected Graph
Thank you Sarang, your post made me find the correct search words for the site.
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 !
I was wondering about a quick to write implementation of a graph in c++. I need the data structure to be easy to manipulate and use graph algorithms(such as BFS,DFS, Kruskal, Dijkstra...).
I need this implementation for an algorithms Olympiad, so the easier to write the data structure the better.
Can you suggest such DS(main structs or classes and what will be in them). I know that an Adjacency list and Adjacency matrix are the main possibilities, but I mean a more detailed code sample.
For example I thought about this DS last time I had to implement a graph for DFS:
struct Edge {
int start;
int end;
struct Edge* nextEdge;
}
and then used a array of size n containing in its i'th place the Edge List(struct Edge) representing the edges starting in the i'th node.
but when trying to DFS on this graph I had to write a 50 line code with about 10 while loops.
What 'good' implementations are there?
Below is a implementation of Graph Data Structure in C++ as Adjacency List.
I have used STL vector for representation of vertices and STL pair for denoting edge and destination vertex.
#include <iostream>
#include <vector>
#include <map>
#include <string>
using namespace std;
struct vertex {
typedef pair<int, vertex*> ve;
vector<ve> adj; //cost of edge, destination vertex
string name;
vertex(string s) : name(s) {}
};
class graph
{
public:
typedef map<string, vertex *> vmap;
vmap work;
void addvertex(const string&);
void addedge(const string& from, const string& to, double cost);
};
void graph::addvertex(const string &name)
{
vmap::iterator itr = work.find(name);
if (itr == work.end())
{
vertex *v;
v = new vertex(name);
work[name] = v;
return;
}
cout << "\nVertex already exists!";
}
void graph::addedge(const string& from, const string& to, double cost)
{
vertex *f = (work.find(from)->second);
vertex *t = (work.find(to)->second);
pair<int, vertex *> edge = make_pair(cost, t);
f->adj.push_back(edge);
}
It really depends on what algorithms you need to implement, there is no silver bullet (and that's shouldn't be a surprise... the general rule about programming is that there's no general rule ;-) ).
I often end up representing directed multigraphs using node/edge structures with pointers... more specifically:
struct Node
{
... payload ...
Link *first_in, *last_in, *first_out, *last_out;
};
struct Link
{
... payload ...
Node *from, *to;
Link *prev_same_from, *next_same_from,
*prev_same_to, *next_same_to;
};
In other words each node has a doubly-linked list of incoming links and a doubly-linked list of outgoing links. Each link knows from and to nodes and is at the same time in two different doubly-linked lists: the list of all links coming out from the same from node and the list of all links arriving at the same to node.
The pointers prev_same_from and next_same_from are used when following the chain of all the links coming out from the same node; the pointers prev_same_to and next_same_to are instead used when managing the chain of all the links pointing to the same node.
It's a lot of pointer twiddling (so unless you love pointers just forget about this) but query and update operations are efficient; for example adding a node or a link is O(1), removing a link is O(1) and removing a node x is O(deg(x)).
Of course depending on the problem, payload size, graph size, graph density this approach can be way overkilling or too much demanding for memory (in addition to payload you've 4 pointers per node and 6 pointers per link).
A similar structure full implementation can be found here.
This question is ancient but for some reason I can't seem to get it out of my mind.
While all of the solutions do provide an implementation of graphs, they are also all very verbose. They are simply not elegant.
Instead of inventing your own graph class all you really need is a way to tell that one point is connected to another -- for that, std::map and std::unordered_map work perfectly fine. Simply, define a graph as a map between nodes and lists of edges. If you don't need extra data on the edge, a list of end nodes will do just fine.
Thus a succinct graph in C++, could be implemented like so:
using graph = std::map<int, std::vector<int>>;
Or, if you need additional data,
struct edge {
int nodes[2];
float cost; // add more if you need it
};
using graph = std::map<int, std::vector<edge>>;
Now your graph structure will plug nicely into the rest of the language and you don't have to remember any new clunky interface -- the old clunky interface will do just fine.
No benchmarks, but I have a feeling this will also outperform the other suggestions here.
NB: the ints are not indices -- they are identifiers.
The most common representations are probably these two:
Adjacency list
Adjacency matrix
Of these two the adjacency matrix is the simplest, as long as you don't mind having a (possibly huge) n * n array, where n is the number of vertices. Depending on the base type of the array, you can even store edge weights for use in e.g. shortest path discovery algorithms.
I prefer using an adjacency list of Indices ( not pointers )
typedef std::vector< Vertex > Vertices;
typedef std::set <int> Neighbours;
struct Vertex {
private:
int data;
public:
Neighbours neighbours;
Vertex( int d ): data(d) {}
Vertex( ): data(-1) {}
bool operator<( const Vertex& ref ) const {
return ( ref.data < data );
}
bool operator==( const Vertex& ref ) const {
return ( ref.data == data );
}
};
class Graph
{
private :
Vertices vertices;
}
void Graph::addEdgeIndices ( int index1, int index2 ) {
vertices[ index1 ].neighbours.insert( index2 );
}
Vertices::iterator Graph::findVertexIndex( int val, bool& res )
{
std::vector<Vertex>::iterator it;
Vertex v(val);
it = std::find( vertices.begin(), vertices.end(), v );
if (it != vertices.end()){
res = true;
return it;
} else {
res = false;
return vertices.end();
}
}
void Graph::addEdge ( int n1, int n2 ) {
bool foundNet1 = false, foundNet2 = false;
Vertices::iterator vit1 = findVertexIndex( n1, foundNet1 );
int node1Index = -1, node2Index = -1;
if ( !foundNet1 ) {
Vertex v1( n1 );
vertices.push_back( v1 );
node1Index = vertices.size() - 1;
} else {
node1Index = vit1 - vertices.begin();
}
Vertices::iterator vit2 = findVertexIndex( n2, foundNet2);
if ( !foundNet2 ) {
Vertex v2( n2 );
vertices.push_back( v2 );
node2Index = vertices.size() - 1;
} else {
node2Index = vit2 - vertices.begin();
}
assert( ( node1Index > -1 ) && ( node1Index < vertices.size()));
assert( ( node2Index > -1 ) && ( node2Index < vertices.size()));
addEdgeIndices( node1Index, node2Index );
}
There can be an even simpler representation assuming that one has to only test graph algorithms not use them(graph) else where. This can be as a map from vertices to their adjacency lists as shown below :-
#include<bits/stdc++.h>
using namespace std;
/* implement the graph as a map from the integer index as a key to the adjacency list
* of the graph implemented as a vector being the value of each individual key. The
* program will be given a matrix of numbers, the first element of each row will
* represent the head of the adjacency list and the rest of the elements will be the
* list of that element in the graph.
*/
typedef map<int, vector<int> > graphType;
int main(){
graphType graph;
int vertices = 0;
cout << "Please enter the number of vertices in the graph :- " << endl;
cin >> vertices;
if(vertices <= 0){
cout << "The number of vertices in the graph can't be less than or equal to 0." << endl;
exit(0);
}
cout << "Please enter the elements of the graph, as an adjacency list, one row after another. " << endl;
for(int i = 0; i <= vertices; i++){
vector<int> adjList; //the vector corresponding to the adjacency list of each vertex
int key = -1, listValue = -1;
string listString;
getline(cin, listString);
if(i != 0){
istringstream iss(listString);
iss >> key;
iss >> listValue;
if(listValue != -1){
adjList.push_back(listValue);
for(; iss >> listValue; ){
adjList.push_back(listValue);
}
graph.insert(graphType::value_type(key, adjList));
}
else
graph.insert(graphType::value_type(key, adjList));
}
}
//print the elements of the graph
cout << "The graph that you entered :- " << endl;
for(graphType::const_iterator iterator = graph.begin(); iterator != graph.end(); ++iterator){
cout << "Key : " << iterator->first << ", values : ";
vector<int>::const_iterator vectBegIter = iterator->second.begin();
vector<int>::const_iterator vectEndIter = iterator->second.end();
for(; vectBegIter != vectEndIter; ++vectBegIter){
cout << *(vectBegIter) << ", ";
}
cout << endl;
}
}
Here is a basic implementation of a graph.
Note: I use vertex which is chained to next vertex. And each vertex has a list pointing to adjacent nodes.
#include <iostream>
using namespace std;
// 1 ->2
// 1->4
// 2 ->3
// 4->3
// 4 -> 5
// Adjacency list
// 1->2->3-null
// 2->3->null
//4->5->null;
// Structure of a vertex
struct vertex {
int i;
struct node *list;
struct vertex *next;
};
typedef struct vertex * VPTR;
// Struct of adjacency list
struct node {
struct vertex * n;
struct node *next;
};
typedef struct node * NODEPTR;
class Graph {
public:
// list of nodes chained together
VPTR V;
Graph() {
V = NULL;
}
void addEdge(int, int);
VPTR addVertex(int);
VPTR existVertex(int i);
void listVertex();
};
// If vertex exist, it returns its pointer else returns NULL
VPTR Graph::existVertex(int i) {
VPTR temp = V;
while(temp != NULL) {
if(temp->i == i) {
return temp;
}
temp = temp->next;
}
return NULL;
}
// Add a new vertex to the end of the vertex list
VPTR Graph::addVertex(int i) {
VPTR temp = new(struct vertex);
temp->list = NULL;
temp->i = i;
temp->next = NULL;
VPTR *curr = &V;
while(*curr) {
curr = &(*curr)->next;
}
*curr = temp;
return temp;
}
// Add a node from vertex i to j.
// first check if i and j exists. If not first add the vertex
// and then add entry of j into adjacency list of i
void Graph::addEdge(int i, int j) {
VPTR v_i = existVertex(i);
VPTR v_j = existVertex(j);
if(v_i == NULL) {
v_i = addVertex(i);
}
if(v_j == NULL) {
v_j = addVertex(j);
}
NODEPTR *temp = &(v_i->list);
while(*temp) {
temp = &(*temp)->next;
}
*temp = new(struct node);
(*temp)->n = v_j;
(*temp)->next = NULL;
}
// List all the vertex.
void Graph::listVertex() {
VPTR temp = V;
while(temp) {
cout <<temp->i <<" ";
temp = temp->next;
}
cout <<"\n";
}
// Client program
int main() {
Graph G;
G.addEdge(1, 2);
G.listVertex();
}
With the above code, you can expand to do DFS/BFS etc.