diff --git a/thu_dsa/chp6/Graph.h b/thu_dsa/chp6/Graph.h index 83a904f..81119ea 100644 --- a/thu_dsa/chp6/Graph.h +++ b/thu_dsa/chp6/Graph.h @@ -13,11 +13,11 @@ template class Graph{ private: void reset(); //reset all information of all vertices and edges - void BFS(int, int&); - void DFS(int, int&); - void BCC(int, int&, Stack&); - bool TSort(int, int&, Stack*); - template void PFS(int, PU); + void BFS(int, int&); //Breadth First Search + void DFS(int, int&); //Depth First Search + void BCC(int, int&, Stack&); //Biconnected Component + bool TSort(int, int&, Stack*); //Topological Sort + template void PFS(int, PU); //Priority First Search public: int num_of_vertices; @@ -52,7 +52,7 @@ public: void prim(int); void dijkstra(int); Stack* tSort(int); - template void pfd(int, PU); + template void pfs(int, PU); }; //private methods @@ -60,7 +60,7 @@ template void Graph::reset(){//reset all information of all vertices and edges for(int ix = 0; ix != num_of_vertices; ++ix){ status(ix) = UNDISCOVERED; - priority(ix) = 0; + priority(ix) = INT_MAX; dtime(ix) = -1; ftime(ix) = -1; parent(ix) = -1; @@ -118,6 +118,85 @@ void Graph::DFS(int x, int& clock){ status(x) = VISITED; } +#define hca(x) ftime(x) +template +void Graph::BCC(int x, int &clock, Stack &S) { + status(x) = DISCOVERED; + S.push(x); + hca(x) = dtime(x) = ++clock; + for (int v = firstNeighbor(x); v != -1; v = nextNeighbor(x, v)) { + switch (status(v)) { + case UNDISCOVERED: + type(x, v) = TREE; + BCC(v, clock, S); + if (hca(v) < dtime(x)) hca(x) = MIN(hca(v), hca(x)); + else {//a biconnected component found + while (S.pop() != x); + S.push(x); + } + break; + + case DISCOVERED: + type(x, v) = BACKWARD; + if (parent(x) != v) hca(x) = MIN(hca(x), dtime(v)); + break; + + case VISITED: + default: + type(x, v) = dtime(x) < dtime(v) ? FORWARD : CROSS; + break; + } + } +} +#undef hca + +template +bool Graph::TSort(int x, int &clock, Stack *S){ + status(x) = DISCOVERED; + dtime(x) = ++clock; + for(int v = firstNeighbor(x); v != -1; v = nextNeighbor(x, v)){ + switch(status(v)){ + case UNDISCOVERED: + status(v) = DISCOVERED; + type(x, v) = TREE; + if (!TSort(v, clock, S)) return false; + break; + + case DISCOVERED: + type(x, v) = BACKWARD; + return false; + + case VISITED: + default: + type(x, v) = dtime(x) > dtime(v)? FORWARD: CROSS; + break; + } + } + S->push(x); + return true; +} + +template +template +void Graph::PFS(int x, PU PrioUpdater){ + priority(x) = 0; + status(x) = VISITED; + parent(x) = -1; + while(1){ + for (int v = firstNeighbor(x); v != -1; v = nextNeighbor(x, v)) + PrioUpdater(this, x, v); + //find current highest priority + for (int shortest = INT_MAX, v = 0; v != num_of_vertices; ++v) + if (status(v) == UNDISCOVERED && priority(v) < shortest) { + shortest = priority(v); + x = v; + } + if (status(x) == VISITED) break; + status(x) == VISITED; + type(parent(x), x) = TREE; + } +} + //Graph related algorithms template @@ -142,4 +221,83 @@ void Graph::dfs(int start){ } while ((x = ++x % num_of_vertices) != start); } -#endif \ No newline at end of file +template +void Graph::bcc(int start){ + reset(); + int clock = 0; + int curr = start; + Stack S; + do{ + if (status(curr) == UNDISCOVERED) { + BCC(curr, clock, S); + S.pop(); //remove the last element in the Stack, which is the start point of current connected components + } + } while ((curr = ++curr % num_of_vertices) ŁĄ = start); +} + +//Prim Algorithm +template +class PrimPU{ +public: + void operator()(Graph *G, int parent, int v){ + if(G->status(v) == UNDISCOVERED){ + if (G->weight(parent, v) < G->priority(v)) { + G->priority = G->weight(parent, v); + G->parent(v) = parent; + } + } + } +}; + +template +void Graph::prim(int x){ + pfs(x, PrimPU()); +} + +//Dijkstra Algorithm + +template +class DijkstraPU{ +public: + void operator()(Graph *G, int parent, int v){ + if(G->status(v) == UNDISCOVERED){ + if(G->priority(parent) + G->weight(parent, v) < G->priority(v)){ + G->priority(v) = G->priority(parent) + G->weight(parent, v); + G->parent(v) = parent; + } + } + } +}; + +template +void Graph::dijkstra(int x){ + pfs(x, DijkstraPU()); +} + +template +Stack* Graph::tSort(int start){ + reset(); + Stack *S; + int clock = 0; + int curr = start; + do{ + if(status(curr) == UNDISCOVERED && !TSort(curr, clock, S)){ + while (!S->empty()) S->pop(); + break; + } + } while ((curr = ++curr % num_of_vertices) != start); + return S; +} + +template +template +void Graph::pfs(int start, PU PrioUpdater){ + reset(); + int curr = start; + do{ + if (status(curr) == UNDISCOVERED) + PFS(curr, PrioUpdater); + } while ((curr = ++curr % num_of_vertices) != start); +} + +#endif diff --git a/thu_dsa/chp6/Graph.md b/thu_dsa/chp6/Graph.md new file mode 100644 index 0000000..4863354 --- /dev/null +++ b/thu_dsa/chp6/Graph.md @@ -0,0 +1,2 @@ +Conclusion on Chapter Six: Graph +================================ \ No newline at end of file diff --git a/thu_dsa/chp6/Vertex.h b/thu_dsa/chp6/Vertex.h index dce10ff..55a3de0 100644 --- a/thu_dsa/chp6/Vertex.h +++ b/thu_dsa/chp6/Vertex.h @@ -11,7 +11,7 @@ public: int parent = -1; int dTime = -1; int fTime = -1; - int priority = 0; + int priority = INT_MAX; int inDegree = 0; int outDegree = 0;