/*
* IA_22.2BreadthFirstSearch.h
*
* Created on: Feb 13, 2015
* Author: sunyj
*/
#ifndef IA_22_2BREADTHFIRSTSEARCH_H_
#define IA_22_2BREADTHFIRSTSEARCH_H_
#include <vector>
#include <map>
#include "IA_10.1queue.h"
#include "IA_10.2LinkedLists.h"
#include <cstdint>
using std::map;
using std::vector;
using std::pair;
using std::cout;
using std::endl;
enum Color { white, grey, black };
class NodeData {
public:
// use INT64_MAX must include <cstdint> and using compiler g++ 4.7.0
// and then g++ -std=c++11, be carefull not c++0x in the centos 64bit operating system
NodeData() : color(white), par(nullptr), depth(INT64_MAX) { }
NodeData(Color const c) : color(c), par(nullptr), depth(INT64_MAX) { }
NodeData(const NodeData& nd)
{
color = nd.color;
par = nd.par;
depth = nd.depth;
}
private:
public:
Color color;
void* par;
int64_t depth;
};
// BFS(G, s)
// for each vertex u belongs to G.V - {s}
// u.color = white
// u.d = INT64_MAX
// u.par = NIL
// s.color = grey
// s.d = 0
// s.par = NIL
// Q = empty
// ENQUEUE(Q, s)
// while(Q != empty)
// u = DEQUEUE(Q);
// for each v belongs to G.Adj[u]
// if v.color == white
// v.color = grey
// v.d = u.d + 1
// v.par = u
// ENQUEUE(Q, v)
// u.color = black
// PRINT-PATH(G, s, v)
// if v == s
// print s
// elseif v.par == NIL
// print "no path from" s "to" v "exists"
// else PRINT-PATH(G, s, v.par)
// print v
template <class Type, class T> class Graph {
public:
typedef Node<Type, T>* PVertex;
bool PrintPath(PVertex s, PVertex v)
{
if (s == v)
{
cout << s->key << " ";
return true;
}
else if (nullptr == v->data.par)
{
cout << "no path from s to v exists" << endl;
return false;
}
else
{
if (PrintPath(s, static_cast<PVertex>(v->data.par)))
{
cout << v->key << " ";
return true;
}
else
{
return false;
}
}
}
// Type: int, charactor
// T: the data that the Node carry
void DFS(PVertex s)
{
s->data.color = grey;
s->data.depth = 0;
QueueDFS.enqueue(s);
while (!QueueDFS.empty())
{
PVertex u;
QueueDFS.dequeue(u);
typename map<Type, LinkedList<Type, PVertex>* >::iterator iter = MapAdj.find(u->key);
if (MapAdj.end() != iter) //
{
Node<Type, PVertex >* pNil = iter->second->GetNil();
Node<Type, PVertex >* x = pNil->next;
while (pNil != x)
{
// cout << x->key << " ";
if (white == (*x->data).data.color)
{
(*x->data).data.color = grey;
(*x->data).data.depth += u->data.depth + 1;
(*x->data).data.par = u;
QueueDFS.enqueue(x->data);
cout << "node " << (*x->data).key << " is grey now" << endl;
}
x = x->next;
}
u->data.color = black;
cout << "node " << u->key << " is black now" << endl;
}
}
return ;
}
Graph(int const n) : MaxCount(n), QueueDFS(MaxCount) { }// assume the graphic has less than 100 vertex
void InsertVertex(Node<Type, T>* v)
{
MapVertex.insert(pair<Type, PVertex >(v->key, v));
LinkedList<Type, PVertex>* pLinkedList = new LinkedList<Type, PVertex>;
MapAdj.insert(pair<Type, LinkedList<Type, PVertex>* >(v->key, pLinkedList));
}
void InsertEdge(PVertex v1, PVertex v2)
{
typename map<Type, PVertex >::const_iterator VIter = MapVertex.find(v1->key);
if (MapVertex.end() == VIter)
{
cout << "v1 is not a vertex of graphic" << endl;
return ;
}
VIter = MapVertex.find(v2->key);
if (MapVertex.end() == VIter)
{
cout << "v2 is not a vertex of graphic" << endl;
return ;
}
typename map<Type, LinkedList<Type, PVertex>* >::iterator iter = MapAdj.find(v1->key);
if (MapAdj.end() != iter) // should be found, otherwise program logic is wrong
{
if (nullptr == iter->second->search(v2->key))
{
// Node<Type, T> is a Type, and the type is for Vertex of Graph
// Type is a Type, and the type is for the key of the Node(Vertex), key is the attr and diff one
// node(Vertex) to another.
// T is a Type, and the type is for other information of the Node(Vertex), something like color, etc.
Node<Type, PVertex >* pNode = new Node<Type, PVertex >;
pNode->data = v2;
pNode->key = v2->key;
iter->second->insert(pNode);
}
else
{
cout << "edge has already exist" << endl;
}
}
}
void PrintAdj(Node<Type, T>* p)
{
typename map<Type, LinkedList<Type, PVertex>* >::iterator iter = MapAdj.find(p->key);
if (MapAdj.end() != iter)
{
Node<Type, PVertex >* pNil = iter->second->GetNil();
Node<Type, PVertex >* x = pNil->next;
while (pNil != x)
{
cout << x->key << " ";
// cout << (*x->data).key << " " ;
x = x->next;
}
cout << endl;
}
}
private:
map<Type, PVertex > MapVertex; // vertex
map<Type, LinkedList<Type, PVertex >* > MapAdj; // adjacency list
int const MaxCount;
queue<PVertex > QueueDFS;
};
#endif /* IA_22_2BREADTHFIRSTSEARCH_H_ */
/*
* IA_22.2BreadthFirstSearch.cpp
*
* Created on: Feb 13, 2015
* Author: sunyj
*/
#include "IA_22.2BreadthFirstSearch.h"
int main()
{
Graph<char, NodeData> g(1000); // 1000 vertex at most
Node<char, NodeData> r('r');
Node<char, NodeData> s('s');
Node<char, NodeData> t('t');
Node<char, NodeData> u('u');
Node<char, NodeData> v('v');
Node<char, NodeData> w('w');
Node<char, NodeData> x('x');
Node<char, NodeData> y('y');
g.InsertVertex(&r);
g.InsertVertex(&s);
g.InsertVertex(&t);
g.InsertVertex(&u);
g.InsertVertex(&v);
g.InsertVertex(&w);
g.InsertVertex(&x);
g.InsertVertex(&y);
g.InsertEdge(&r, &s);
g.InsertEdge(&r, &v);
g.InsertEdge(&s, &r);
g.InsertEdge(&s, &w);
g.InsertEdge(&w, &x);
g.InsertEdge(&w, &t);
g.InsertEdge(&t, &x);
g.InsertEdge(&t, &u);
g.InsertEdge(&x, &y);
g.InsertEdge(&x, &u);
g.InsertEdge(&u, &y);
g.InsertEdge(&v, &r);
g.InsertEdge(&w, &s);
g.InsertEdge(&t, &w);
g.InsertEdge(&x, &w);
g.InsertEdge(&x, &t);
g.InsertEdge(&u, &t);
g.InsertEdge(&y, &x);
g.InsertEdge(&u, &x);
g.InsertEdge(&y, &u);
g.PrintAdj(&r);
g.PrintAdj(&s);
g.PrintAdj(&t);
g.PrintAdj(&u);
g.PrintAdj(&v);
g.PrintAdj(&w);
g.PrintAdj(&x);
g.PrintAdj(&y);
g.DFS(&s);
g.PrintPath(&r, &v);
cout << endl;
g.PrintPath(&s, &v);
cout << endl;
g.PrintPath(&s, &t);
cout << endl;
g.PrintPath(&s, &x);
cout << endl;
g.PrintPath(&s, &y);
cout << endl;
g.PrintPath(&r, &x);
cout << endl;
return 0;
}



