算法导论 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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值