[关闭]
@CrazyHenry 2018-03-26T20:55:40.000000Z 字数 4788 阅读 920

0.x 15.图论基础-有权图表示

dddd数据结构课本


有权图的表示

边的表示和图信息的读取

  1. #include <iostream>
  2. #include <cassert>
  3. using namespace std;
  4. // 边
  5. template<typename Weight>
  6. class Edge{
  7. private:
  8. int a,b; // 边的两个端点
  9. Weight weight; // 边的权值
  10. public:
  11. // 构造函数
  12. Edge(int a, int b, Weight weight){
  13. this->a = a;
  14. this->b = b;
  15. this->weight = weight;
  16. }
  17. // 空的构造函数, 所有的成员变量都取默认值
  18. Edge(){}
  19. ~Edge(){}
  20. int v(){ return a;} // 返回第一个顶点
  21. int w(){ return b;} // 返回第二个顶点
  22. Weight wt(){ return weight;} // 返回权值
  23. // 给定一个顶点, 返回另一个顶点
  24. int other(int x){
  25. assert( x == a || x == b );
  26. return x == a ? b : a;
  27. }
  28. // 输出边的信息
  29. friend ostream& operator<<(ostream &os, const Edge &e){
  30. os<<e.a<<"-"<<e.b<<": "<<e.weight;
  31. return os;
  32. }
  33. // 边的大小比较, 是对边的权值的大小比较
  34. bool operator<(Edge<Weight>& e){
  35. return weight < e.wt();
  36. }
  37. bool operator<=(Edge<Weight>& e){
  38. return weight <= e.wt();
  39. }
  40. bool operator>(Edge<Weight>& e){
  41. return weight > e.wt();
  42. }
  43. bool operator>=(Edge<Weight>& e){
  44. return weight >= e.wt();
  45. }
  46. bool operator==(Edge<Weight>& e){
  47. return weight == e.wt();
  48. }
  49. };
  1. #include <iostream>
  2. #include <string>
  3. #include <fstream>
  4. #include <sstream>
  5. #include <cassert>
  6. using namespace std;
  7. // 读取有权图
  8. template <typename Graph, typename Weight>
  9. class ReadGraph{
  10. public:
  11. // 从文件filename中读取有权图的信息, 存储进图graph中
  12. ReadGraph(Graph &graph, const string &filename){
  13. ifstream file(filename);
  14. string line;
  15. int V, E;
  16. assert(file.is_open());
  17. // 第一行读取图中的节点个数和边的个数
  18. assert( getline(file,line));
  19. stringstream ss(line);
  20. ss >> V >> E;
  21. assert( graph.V() == V );
  22. // 读取每一条边的信息
  23. for( int i = 0 ; i < E ; i ++ ){
  24. assert( getline(file,line));
  25. stringstream ss(line);
  26. int a, b;
  27. Weight w;
  28. ss>>a>>b>>w;
  29. assert( a >= 0 && a < V );
  30. assert( b >= 0 && b < V );
  31. graph.addEdge(a, b, w);
  32. }
  33. }
  34. };

邻接矩阵

  1. #include <iostream>
  2. #include <vector>
  3. #include <cassert>
  4. #include "Edge.h"
  5. using namespace std;
  6. // 稠密图 - 邻接矩阵
  7. template <typename Weight>
  8. class DenseGraph{
  9. private:
  10. int n, m; // 节点数和边数
  11. bool directed; // 是否为有向图
  12. vector<vector<Edge<Weight> *>> g; // 图的具体数据
  13. public:
  14. // 构造函数
  15. DenseGraph( int n , bool directed){
  16. assert( n >= 0 );
  17. this->n = n;
  18. this->m = 0;
  19. this->directed = directed;
  20. // g初始化为n*n的矩阵, 每一个g[i][j]指向一个边的信息, 初始化为NULL
  21. g = vector<vector<Edge<Weight> *>>(n, vector<Edge<Weight> *>(n, NULL));
  22. }
  23. // 析构函数
  24. ~DenseGraph(){
  25. for( int i = 0 ; i < n ; i ++ )
  26. for( int j = 0 ; j < n ; j ++ )
  27. if( g[i][j] != NULL )
  28. delete g[i][j];
  29. }
  30. int V(){ return n;} // 返回节点个数
  31. int E(){ return m;} // 返回边的个数
  32. // 向图中添加一个边, 权值为weight
  33. void addEdge( int v, int w , Weight weight ){
  34. assert( v >= 0 && v < n );
  35. assert( w >= 0 && w < n );
  36. // 如果从v到w已经有边, 删除这条边
  37. if( hasEdge( v , w ) ){
  38. delete g[v][w];
  39. if( v != w && !directed )
  40. delete g[w][v];
  41. m --;
  42. }
  43. g[v][w] = new Edge<Weight>(v, w, weight);
  44. if( v != w && !directed )
  45. g[w][v] = new Edge<Weight>(w, v, weight);
  46. m ++;
  47. }
  48. // 验证图中是否有从v到w的边
  49. bool hasEdge( int v , int w ){
  50. assert( v >= 0 && v < n );
  51. assert( w >= 0 && w < n );
  52. return g[v][w] != NULL;
  53. }
  54. // 显示图的信息
  55. void show(){
  56. for( int i = 0 ; i < n ; i ++ ){
  57. for( int j = 0 ; j < n ; j ++ )
  58. if( g[i][j] )
  59. cout<<g[i][j]->wt()<<"\t";
  60. else
  61. cout<<"NULL\t";
  62. cout<<endl;
  63. }
  64. }
  65. // 邻边迭代器, 传入一个图和一个顶点,
  66. // 迭代在这个图中和这个顶点向连的所有边
  67. class adjIterator{
  68. private:
  69. DenseGraph &G; // 图G的引用
  70. int v;
  71. int index;
  72. public:
  73. // 构造函数
  74. adjIterator(DenseGraph &graph, int v): G(graph){
  75. this->v = v;
  76. this->index = -1; // 索引从-1开始, 因为每次遍历都需要调用一次next()
  77. }
  78. ~adjIterator(){}
  79. // 返回图G中与顶点v相连接的第一个边
  80. Edge<Weight>* begin(){
  81. // 索引从-1开始, 因为每次遍历都需要调用一次next()
  82. index = -1;
  83. return next();
  84. }
  85. // 返回图G中与顶点v相连接的下一个边
  86. Edge<Weight>* next(){
  87. // 从当前index开始向后搜索, 直到找到一个g[v][index]为true
  88. for( index += 1 ; index < G.V() ; index ++ )
  89. if( G.g[v][index] )
  90. return G.g[v][index];
  91. // 若没有顶点和v相连接, 则返回NULL
  92. return NULL;
  93. }
  94. // 查看是否已经迭代完了图G中与顶点v相连接的所有边
  95. bool end(){
  96. return index >= G.V();
  97. }
  98. };
  99. };

邻接表

  1. #include <iostream>
  2. #include <vector>
  3. #include <cassert>
  4. #include "Edge.h"
  5. using namespace std;
  6. // 稀疏图 - 邻接表
  7. template<typename Weight>
  8. class SparseGraph{
  9. private:
  10. int n, m; // 节点数和边数
  11. bool directed; // 是否为有向图
  12. vector<vector<Edge<Weight> *> > g; // 图的具体数据
  13. public:
  14. // 构造函数
  15. SparseGraph( int n , bool directed){
  16. assert(n >= 0);
  17. this->n = n;
  18. this->m = 0; // 初始化没有任何边
  19. this->directed = directed;
  20. // g初始化为n个空的vector, 表示每一个g[i]都为空, 即没有任和边
  21. g = vector<vector<Edge<Weight> *> >(n, vector<Edge<Weight> *>());
  22. }
  23. // 析构函数
  24. ~SparseGraph(){
  25. for( int i = 0 ; i < n ; i ++ )
  26. for( int j = 0 ; j < g[i].size() ; j ++ )
  27. delete g[i][j];
  28. }
  29. int V(){ return n;} // 返回节点个数
  30. int E(){ return m;} // 返回边的个数
  31. // 向图中添加一个边, 权值为weight
  32. void addEdge( int v, int w , Weight weight){
  33. assert( v >= 0 && v < n );
  34. assert( w >= 0 && w < n );
  35. // 注意, 由于在邻接表的情况, 查找是否有重边需要遍历整个链表
  36. // 我们的程序允许重边的出现
  37. g[v].push_back(new Edge<Weight>(v, w, weight));
  38. if( v != w && !directed )
  39. g[w].push_back(new Edge<Weight>(w, v, weight));
  40. m ++;
  41. }
  42. // 验证图中是否有从v到w的边
  43. bool hasEdge( int v , int w ){
  44. assert( v >= 0 && v < n );
  45. assert( w >= 0 && w < n );
  46. for( int i = 0 ; i < g[v].size() ; i ++ )
  47. if( g[v][i]->other(v) == w )
  48. return true;
  49. return false;
  50. }
  51. // 显示图的信息
  52. void show(){
  53. for( int i = 0 ; i < n ; i ++ ){
  54. cout<<"vertex "<<i<<":\t";
  55. for( int j = 0 ; j < g[i].size() ; j ++ )
  56. cout<<"( to:"<<g[i][j]->w()<<",wt:"<<g[i][j]->wt()<<")\t";
  57. cout<<endl;
  58. }
  59. }
  60. // 邻边迭代器, 传入一个图和一个顶点,
  61. // 迭代在这个图中和这个顶点向连的所有边
  62. class adjIterator{
  63. private:
  64. SparseGraph &G; // 图G的引用
  65. int v;
  66. int index;
  67. public:
  68. // 构造函数
  69. adjIterator(SparseGraph &graph, int v): G(graph){
  70. this->v = v;
  71. this->index = 0;
  72. }
  73. ~adjIterator(){}
  74. // 返回图G中与顶点v相连接的第一个边
  75. Edge<Weight>* begin(){
  76. index = 0;
  77. if( G.g[v].size() )
  78. return G.g[v][index];
  79. // 若没有顶点和v相连接, 则返回NULL
  80. return NULL;
  81. }
  82. // 返回图G中与顶点v相连接的下一个边
  83. Edge<Weight>* next(){
  84. index += 1;
  85. if( index < G.g[v].size() )
  86. return G.g[v][index];
  87. return NULL;
  88. }
  89. // 查看是否已经迭代完了图G中与顶点v相连接的所有顶点
  90. bool end(){
  91. return index >= G.g[v].size();
  92. }
  93. };
  94. };
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注