Check for existence of a path from "start" node to "end" node in a directed graph.
/*
* CheckPathExistsFromStartToEnd.cpp
*
* Created on: May 07, 2012
* Author: Kiran Hegde
*/
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
class GraphNode {
public :
enum State {NotVisited, Visited};
GraphNode(int d): data(d) {}
~GraphNode() {
vector<GraphNode *>::iterator it;
for (it = adjacentNodes.begin(); it < adjacentNodes.end(); it++) {
delete (*it);
}
}
void addNode(GraphNode *node) {
adjacentNodes.push_back(node);
}
vector<GraphNode *> adjacentNodes;
State state;
int data;
};
/**
* Collection of interconnected nodes
*/
class Graph {
public:
void addNode(GraphNode *node) {
nodes.push_back(node);
}
vector<GraphNode *> nodes;
};
/**
* Print each node and its adjacent nodes (directed)
*/
void printGraph(Graph *graph) {
if (graph == NULL){
return;
}
vector<GraphNode *>::iterator it1;
for (it1 = graph->nodes.begin(); it1 < graph->nodes.end(); it1++) {
cout << "Node: " << (*it1)->data << " --> adjacent: ";
vector<GraphNode *>::iterator it2;
for (it2 = (*it1)->adjacentNodes.begin();
it2 < (*it1)->adjacentNodes.end(); it2++) {
cout << (*it2)->data << " " ;
}
cout << endl;
}
}
/**
* Create a directed graph
*/
Graph *createGraph() {
GraphNode *n0 = new GraphNode(0);
GraphNode *n1 = new GraphNode(1);
GraphNode *n2 = new GraphNode(2);
GraphNode *n3 = new GraphNode(3);
GraphNode *n4 = new GraphNode(4);
GraphNode *n5 = new GraphNode(5);
GraphNode *n6 = new GraphNode(6);
GraphNode *n7 = new GraphNode(7);
GraphNode *n8 = new GraphNode(8);
n0->addNode(n1);
n0->addNode(n2);
n0->addNode(n3);
n1->addNode(n2);
n1->addNode(n4);
n3->addNode(n2);
n3->addNode(n6);
n4->addNode(n5);
n5->addNode(n7);
n5->addNode(n8);
n6->addNode(n5);
n6->addNode(n7);
Graph *graph = new Graph();
graph->addNode(n0);
graph->addNode(n1);
graph->addNode(n2);
graph->addNode(n3);
graph->addNode(n4);
graph->addNode(n5);
graph->addNode(n6);
graph->addNode(n7);
graph->addNode(n8);
return graph;
}
/**
* Essentially a Breadth First Search (BFS) algorithm
*/
bool doesPathExist(Graph *graph, GraphNode *start, GraphNode *end) {
if (graph == NULL)
return false;
vector<GraphNode *>::iterator it;
// To begin with mark all nodes as "Not Visited"
for (it = graph->nodes.begin(); it < graph->nodes.end(); it++) {
(*it)->state = GraphNode::NotVisited;
}
queue<GraphNode *> nodesQueue;
// First enqueue the start node
nodesQueue.push(start);
/* Dequeue the node from the queue and examine it
* if queue is empty, every node in the graph has been examined and the
* desired node was not found */
while(! nodesQueue.empty()) {
GraphNode *node = nodesQueue.front();
nodesQueue.pop();
if (node != NULL) {
//if node is found return true
if (node == end)
return true;
vector<GraphNode *>::iterator it1;
for (it1 = node->adjacentNodes.begin(); it1 < node->adjacentNodes.end(); it1++) {
//enqueue adjacent nodes that have not been visited yet
if ((*it1)->state == GraphNode::NotVisited) {
nodesQueue.push(*it1);
}
}
//Mark current node as visited
node->state = GraphNode::Visited;
}
}
return false;
}
/**
* Test the code
*/
int main() {
Graph *graph = createGraph();
printGraph(graph);
GraphNode *start = graph->nodes[2];
GraphNode *end = graph->nodes[3];
cout << endl;
cout << "Path: from node " << start->data << " to " << end->data <<
" exists: "<< (doesPathExist(graph, start, end) ? "Yes" : "No") << endl;
start = graph->nodes[3];
end = graph->nodes[8];
cout << "Path: from node " << start->data << " to " << end->data <<
" exists: "<< (doesPathExist(graph, start, end) ? "Yes" : "No") << endl;
}