算法导论 ch22 图的基本算法

1. 图的表示:邻接矩阵,邻接表

2. 图的遍历:广度优先遍历,深度优先遍历(非递归)

3. 注:BFS通常用于从某个源节点开始,寻找最短路径距离,DFS通常作为另一个算法的一个子程序。

 

1) Edge.h

 

#ifndef EDGE_H_ #define EDGE_H_ #include <iostream> using namespace std; class Edge { public: int from; int to; Edge *next; // Edge(int f = -1, int t = -1, Edge* n = NULL) : // from(f), to(t), next(n) { // } }; ostream& operator <<(ostream& os, Edge *q){ if(!q){ cerr << "null Edge!" << endl; }else{ os << "(" << q->from << ", " << q->to << ")"; } return os; } class Edges { public: void insert(Edge* e) { e->next = head; head = e; } static Edges* getInstance(){ if(!_instance){ _instance = new Edges(); } return _instance; } Edge* head; private: Edges(Edge* h = NULL):head(h){ } static Edges* _instance; }; // static variable initialization Edges* Edges::_instance = NULL; ostream& operator <<(ostream& os, Edges *q){ if(!q){ cerr << "null Edges!" << endl; }else{ Edge* p = q->head; while(p){ os << p << " "; p = p->next; } os << endl; } return os; } #endif /*EDGE_H_*/

 

2) Graph.h

 

#ifndef GRAPH_H_ #define GRAPH_H_ #include "Edge.h" #include "List.h" #include "GraphBuilder.h" #include <queue> #include <stack> #include <limits> enum COLOR { WHITE, GRAY, BLACK }; // the current visit vertex v and its edge n class Frame { public: int v; Node* n; Frame(int _v = -1, Node *_n = NULL) : v(_v), n(_n) { } }; class Graph { public: Graph(int _v = 0, Edges* _e = NULL, bool directed = false) : v(_v), edges(_e), isDirected(directed) { } Edges* getEdges() const { return edges; } virtual Graph* getTranspose() = 0; virtual Graph* getSquare() = 0; virtual void build(GraphBuilder *b) = 0; virtual void display() = 0; virtual int bfs(int s) = 0; virtual void diameter() = 0; virtual void dfs() = 0; protected: int v; Edges* edges; bool isDirected; }; class AdjMatrixGraph : public Graph { public: friend class MatrixGraphBuilder; AdjMatrixGraph(int _v = 0, Edges* _e = NULL, bool directed = false) : Graph(_v, _e, directed) { A = new int[_v*_v]; // reset the matrix for (int i = 0; i < _v; i++) { for (int j = 0; j < _v; j++) { A[i * _v + j] = 0; } } } void build(GraphBuilder *b) { b->buildMatrix(this); } void display() { for (int i = 0; i < v; i++) { for (int j = 0; j < v; j++) { cout << A[i * v + j]<< " "; } cout << endl; } cout << endl; } Graph* getTranspose() { AdjMatrixGraph *g = new AdjMatrixGraph(v); for (int i = 0; i < v; i++) { for (int j = 0; j < v; j++) { g->A[j * v + i] = A[i * v + j]; } } return g; } Graph* getSquare() { AdjMatrixGraph *g = new AdjMatrixGraph(v); for (int i = 0; i < v; i++) { for (int j = 0; j < v; j++) { for (int k = 0; k < v; k++) { if ( (i != j) && A[i * v + k ]&& A[k * v + j]) { g->A[i * v + j] = 1; break; } } } } return g; } int bfs(int s) { COLOR *c = new COLOR[v]; int *d = new int[v]; int *p = new int[v]; for (int i = 0; i < v; i++) { c[i] = WHITE; d[i] = numeric_limits<int>::max(); p[i] = -1; } c[s] = GRAY; d[s] = 0; p[s] = -1; queue<int> q; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); for (int j = 0; j < v; j++) { if ((j != u ) && (A[u * v + j] > 0)&& (c[j] == WHITE)) { c[j] = GRAY; d[j] = d[u] + 1; p[j] = u; q.push(j); } } c[u] = BLACK; } for (int i = 0; i < v; i++) { cout << i << " : "<< c[i]<< " "<< d[i]<< " "<< p[i]<< endl; if (p[i] == -1) { cout << "no path from "<< s << " to "<< i << endl; } else { int pp = p[i]; while (pp != -1) { cout << pp << " "; pp = p[pp]; } } cout << endl; } return 0; } void diameter() { } void dfs() { } private: int *A; }; class AdjListGraph : public Graph { friend class ListGraphBuilder; private: List* A; public: AdjListGraph(int _v = 0, Edges* _e = NULL, bool directed = false) : Graph(_v, _e, directed) { A = new List[_v]; } void build(GraphBuilder *b) { b->buildList(this); } void display() { for (int i = 0; i < v; i++) { List l = A[i]; Node* p = l.head; cout << "["<< i << "] "; while (p) { cout << "->"<< p->v<< " "; p = p->next; } cout << endl; } cout << endl; } Graph* getTranspose() { AdjListGraph *g = new AdjListGraph(v); for (int i = 0; i < v; i++) { List l = A[i]; Node* p = l.head; while (p) { int to = p->v; Node * node = new Node(i); (g->A[to]).insertBack(node); p = p->next; } } return g; } Graph* getSquare() { AdjListGraph *g = new AdjListGraph(v); for (int i = 0; i < v; i++) { List p = A[i]; Node* pn = p.head; while (pn) { int to = pn->v; List q = A[to]; Node* qn = q.head; while (qn) { int qv = qn->v; Node *node = new Node(qv); (g->A[i]).insertBack(node); qn = qn->next; } pn = pn->next; } } return g; } int bfs(int s) { COLOR *c = new COLOR[v]; int *d = new int[v]; int *p = new int[v]; for (int i = 0; i < v; i++) { c[i] = WHITE; d[i] = numeric_limits<int>::max(); p[i] = -1; } c[s] = GRAY; d[s] = 0; p[s] = -1; queue<int> q; q.push(s); while (!q.empty()) { int u = q.front(); q.pop(); List l = A[u]; Node* h = l.head; while (h) { int v = h->v; if (c[v] == WHITE) { c[v] = GRAY; d[v] = d[u] + 1; p[v] = u; q.push(v); } h = h->next; } c[u] = BLACK; } // for (int i = 0; i < v; i++) { // cout << i << " : " << c[i] << " " << d[i] << " " << p[i] << endl; // if (p[i] == -1){ // cout << "no path from " << s << " to " << i << endl; // }else{ // int pp = p[i]; // while(pp != -1){ // cout << pp << " "; // pp = p[pp]; // } // } // cout << endl; // } // distance is the height of tree int distance = 0; for (int i = 0; i < v; i++) { if (distance < d[i]) { distance = d[i]; } } return distance; } void diameter() { int d = 0, j = -1, i = 0; for (; i < v; i++) { int distance = bfs(i); if (d < distance) { d = distance; j = i; } } cout << "the diameter is "<< d << ", from "<< i << endl; } void dfs() { COLOR *c = new COLOR[v]; int *p = new int[v]; // discover time int *d = new int[v]; // finish time int *f = new int[v]; // connection component int *cc = new int[v]; int time = 0; int com = 0; for (int i = 0; i < v; i++) { c[i] = WHITE; p[i] = -1; d[i] = 0; f[i] = 0; cc[i] = -1; } // begin search stack<Frame*> s; for (int i = 0; i < v; i++) { if (c[i] == WHITE) { c[i] = GRAY; time++; com++; d[i] = time; cc[i] = com; Node* h = A[i].head; s.push(new Frame(i, h)); while (!s.empty()) { Frame *fm = s.top(); Node* curEdge = fm->n; if (curEdge) { int cur = curEdge->v; switch (c[cur]) { case WHITE: cout << "(" << fm->v << ", " << cur << ") tree edge" << endl; c[cur] = GRAY; time++; cc[cur] = com; d[cur] = time; p[cur] = fm->v; s.push(new Frame(cur, A[cur].head)); break; case GRAY: cout << "(" << fm->v << ", " << cur << ") back edge" << endl; // find a back edge s.pop(); s.push(new Frame(fm->v, fm->n->next)); break; case BLACK: // find a front edge or cross edge if (cc[fm->v] == cc[cur]){ cout << "(" << fm->v << ", " << cur << ") front edge" << endl; }else{ cout << "(" << fm->v << ", " << cur << ") cross edge" << endl; } s.pop(); s.push(new Frame(fm->v, fm->n->next)); break; default: break; } } else { s.pop(); // finish visit f.v c[fm->v] = BLACK; f[fm->v] = ++time; } } } } for (int j = 0; j < v; j++) { cout << "vertex "<< j << " : component " << cc[j] << " ("<< d[j]<< ", "<< f[j] << ")" << endl; } } }; void MatrixGraphBuilder::buildMatrix(Graph* _g) { AdjMatrixGraph* g = dynamic_cast<AdjMatrixGraph*>(_g); if (!g) { return; } Edges* e = g->getEdges(); Edge* p = e->head; while (p) { int from = p->from - 1; int to = p->to - 1; int v = g->v; g->A[from * v + to] = 1; p = p->next; } } void ListGraphBuilder::buildList(Graph* _g) { AdjListGraph* g = dynamic_cast<AdjListGraph*>(_g); if (!g) { return; } Edges* e = g->getEdges(); Edge* p = e->head; List* A = g->A; while (p) { int from = p->from - 1; int to = p->to - 1; Node *node = new Node(to); (A[from]).insertBack(node); p = p->next; } } #endif /*GRAPH_H_*/

 

3) GraphBuilder.h

 

#ifndef GRAPHBUILDER_H_ #define GRAPHBUILDER_H_ class Graph; class AdjMatrixGraph; class AdjListGraph; class GraphBuilder { public: virtual void buildMatrix(Graph* g) { } ; virtual void buildList(Graph* g) { } ; }; class MatrixGraphBuilder : public GraphBuilder { public: static MatrixGraphBuilder* getInstance() { if (!_instance) { _instance = new MatrixGraphBuilder(); } return _instance; } void buildMatrix(Graph* g); private: MatrixGraphBuilder() { } static MatrixGraphBuilder* _instance; }; MatrixGraphBuilder* MatrixGraphBuilder::_instance= NULL; class ListGraphBuilder : public GraphBuilder { public: static ListGraphBuilder* getInstance() { if (!_instance) { _instance = new ListGraphBuilder(); } return _instance; } void buildList(Graph* g); private: ListGraphBuilder() { } static ListGraphBuilder* _instance; }; ListGraphBuilder* ListGraphBuilder::_instance= NULL; #endif /*GRAPHBUILDER_H_*/

 

4) List.h

 

#ifndef LIST_H_ #define LIST_H_ class Node { public: Node(int _v = -1, Node* _next = NULL) : v(_v), next(_next) { } int v; Node* next; }; class List { public: List() { head = NULL; } void insertFront(Node* p) { p->next = head; head = p; } // check duplicate void insertBack(Node* p) { Node* q = head, *pre= NULL; while (q) { if (q->v == p->v) { return; } pre = q; q = q->next; } p->next = NULL; if (!pre) { // head is NULL head = p; } else { pre->next = p; } } public: Node* head; }; #endif /*LIST_H_*/

 

5) Test.cpp

 

#include "Graph.h" int main(){ // Edge e[] = {{1,2}, {1,5}, {2,1}, {2,3}, {2,4}, {2,5}, {3,2}, {3,4}, {4,2}, {4,3}, {4,5}, {5,1}, {5,2}, {5,4}}; Edge e[] = {{1,2}, {1,4}, {2,5}, {3,5}, {3,6}, {4,2}, {5,4}}; Edges* edges = Edges::getInstance(); for(int i = 0; i < sizeof(e)/sizeof(Edge); i++){ edges->insert(&(e[i])); } // AdjMatrixGraph *g1 = new AdjMatrixGraph(5, edges); // MatrixGraphBuilder* mgb = MatrixGraphBuilder::getInstance(); // g1->build(mgb); // g1->display(); // g1->bfs(0); // Graph *g1t = g1->getTranspose(); // g1t->display(); // g1t = g1->getSquare(); // g1t->display(); AdjListGraph *g2 = new AdjListGraph(6, edges); ListGraphBuilder *lgb = ListGraphBuilder::getInstance(); g2->build(lgb); g2->display(); // Graph *g2t = g2->getTranspose(); // g2t->display(); // g2t = g2->getSquare(); // g2t->display(); // g2->bfs(0); // g2->diameter(); g2->dfs(); return 0; }

 

6) 测试结果

 

[0] ->3 ->1 [1] ->4 [2] ->5 ->4 [3] ->1 [4] ->3 [5] (0, 3) tree edge (3, 1) tree edge (1, 4) tree edge (4, 3) back edge (1, 4) front edge (3, 1) front edge (0, 3) front edge (0, 1) front edge (2, 5) tree edge (2, 5) front edge (2, 4) cross edge vertex 0 : component 1 (1, 8) vertex 1 : component 1 (3, 6) vertex 2 : component 2 (9, 12) vertex 3 : component 1 (2, 7) vertex 4 : component 1 (4, 5) vertex 5 : component 2 (10, 11)

 

你可能感兴趣的:(算法导论 ch22 图的基本算法)