【数据结构】图Graph的邻接矩阵,邻接表及深度、广度遍历

前端之家收集整理的这篇文章主要介绍了【数据结构】图Graph的邻接矩阵,邻接表及深度、广度遍历前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

图的分类

有/无向图

如果给图的每条边规定一个方向,那么得到的图称为有向图。在有向图中,与一个节点相关联的边有出边和入边之分。相反,边没有方向的图称为无向图
下面介绍图的两种存储结构

1、邻接矩阵

用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边或弧)的数据,这个二维数组称为邻接矩阵。邻接矩阵又分为有向图邻接矩阵和无向图邻接矩阵

邻接矩阵的思想图

代码实现

  1. int GetIndex(const V& v)//获取顶点
  2. {
  3. for (size_t i=0;i<_size;i++)
  4. {
  5. if(_vertex[i]==v)
  6. return i;
  7. }
  8. throw std::invalid_argument("顶点赋值错误");
  9. }
  10. void AddEdge(const V& src,const V& dst,const W& w)//增加矩阵中的点
  11. {
  12. size_t srcIndex=GetIndex(src);
  13. size_t dstIndex=GetIndex(dst);
  14. _matrix[srcIndex][dstIndex]=w;
  15. if(_isDirection==false)
  16. _matrix[dstIndex][srcIndex]=w;
  17. }

2、邻接表

图的邻接矩阵存储方法跟树的孩子链表示法相类似,是一种顺序分配和链式分配相结合的存储结构。如这个表头结点所对应的顶点存在相邻顶点,则把相邻顶点依次存放于表头结点所指向的单向链表中。

邻接表的思想图


邻接表的代码实现

  1. int GetIndex(const V& v)
  2. {
  3. for (int i=0;i<_vertex.size();i++)
  4. {
  5. if(_vertex[i]==v)
  6. return i;
  7. }
  8. throw std::invalid_argument("顶点赋值错误");
  9. }
  10. void _AddEdge(size_t src,size_t dst,const W& w)
  11. {
  12. // _table[src][dst]._w=w;
  13. Node* cur=new Node(src,dst,w);
  14. cur->Next=_table[src];
  15. _table[src]=cur;
  16. }
  17. void AddEdge(const V& src,const W& w)
  18. {
  19. int srcIndex=GetIndex(src);
  20. int dstIndex=GetIndex(dst);
  21. if (_isDirection)
  22. {
  23. _AddEdge(srcIndex,dstIndex,w);
  24. }
  25. else
  26. {
  27. _AddEdge(srcIndex,w);
  28. _AddEdge(dstIndex,srcIndex,w);
  29. }
  30. }

邻接表的深度优先遍历,类似于二叉树的前序遍历

一个节点知道遍历到无路可走才遍历旁边的节点


代码实现,这里用vector实现

  1. void DFS(const V& v)
  2. {
  3. vector<bool> visted(_vertex.size(),false);
  4. cout<<v;
  5. _DFS(GetIndex(v),visted);
  6. for(size_t i=0;i<_vertex.size();i++)
  7. {
  8. if(visted[i]==false)
  9. {
  10. cout<<_vertex[i];
  11. visted[i]=true;
  12. _DFS(i,visted);
  13. }
  14. }
  15. cout<<"NULL"<<endl;
  16. }
  17. void _DFS(size_t src,vector<bool>& visted)
  18. {
  19. visted[src]=true;
  20. Node* cur=_table[src];
  21. cout<<"["<<src<<"]->";
  22. while (cur)
  23. {
  24. if(visted[cur->_dst]==false)
  25. {
  26. cout<<_vertex[cur->_dst];
  27. visted[cur->_dst]=true;
  28. _DFS(cur->_dst,visted);
  29. }
  30. cur=cur->Next;
  31. }
  32. }

邻接表的广度优先遍历

一个节点把它周围的节点全部都遍历完,才会进行前进遍历

代码实现,这里用队列实现,队列有先进先出的特点,符合此算法

  1. void _BFS(size_t src,vector<bool>& visted)
  2. {
  3. visted[src]=true;
  4. cout<<"["<<src<<"]->";
  5. queue<size_t> q;
  6. q.push(src);
  7. while (!q.empty())
  8. {
  9. src=q.front();
  10. q.pop();
  11. Node* cur=_table[src];
  12. while (cur)
  13. {
  14. if(visted[cur->_dst]==false)
  15. {
  16. cout<<_vertex[cur->_dst]<<"["<<cur->_dst<<"]"<<"-> ";
  17. visted[cur->_dst]=true;
  18. q.push(cur->_dst);
  19. }
  20. cur=cur->Next;
  21. }
  22. }
  23. cout<<endl;
  24. }
  25. void BFS(const V& v)
  26. {
  27. vector<bool> visted(_vertex.size(),false);
  28. cout<<v;
  29. _BFS(GetIndex(v),visted);
  30. }

附全部代码及其测试
临街矩阵

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. using namespace std;
  5. template<class V,class W>
  6. class GraphMatrix
  7. {
  8. public:
  9. GraphMatrix(V* vertex,size_t size,bool isDirection=false,const int invalid=0 )
  10. :_vertex(new V[size]),_size(size),_isDirection(isDirection)
  11. {
  12. _matrix=new W*[size];
  13. for(size_t i=0;i<size;i++)
  14. {
  15. _vertex[i]=vertex[i];
  16. _matrix[i]=new W[size];
  17. for (size_t j=0;j<size;j++)
  18. {
  19. _matrix[i][j]=invalid;
  20. }
  21. }
  22. }
  23. ~GraphMatrix()
  24. {
  25. delete[] _vertex;
  26. delete[] _matrix;
  27. _size=0;
  28. }
  29. int GetIndex(const V& v)//获取顶点
  30. {
  31. for (size_t i=0;i<_size;i++)
  32. {
  33. if(_vertex[i]==v)
  34. return i;
  35. }
  36. throw std::invalid_argument("顶点赋值错误");
  37. }
  38. void AddEdge(const V& src,const W& w)//增加矩阵中的点
  39. {
  40. size_t srcIndex=GetIndex(src);
  41. size_t dstIndex=GetIndex(dst);
  42. _matrix[srcIndex][dstIndex]=w;
  43. if(_isDirection==false)
  44. _matrix[dstIndex][srcIndex]=w;
  45. }
  46. void PrintMaxtix()
  47. {
  48. for(size_t i=0;i<_size;i++)
  49. {
  50. for(size_t j=0;j<_size;j++)
  51. {
  52. cout<<_matrix[i][j]<<" ";
  53. }
  54. cout<<endl;
  55. }
  56. }
  57. protected:
  58. V* _vertex;
  59. W** _matrix;
  60. size_t _size;
  61. bool _isDirection;
  62. };
  63. void TestGraphMatrix()
  64. {
  65. string v[4]={"西安","宝鸡","咸阳","延安"};
  66. GraphMatrix<string,size_t> gm(v,4);//无向图
  67. cout<<"无向图邻接矩阵:"<<endl;
  68. gm.AddEdge("西安",7);
  69. gm.AddEdge("西安",200);
  70. gm.AddEdge("西安","延安",500);
  71. gm.AddEdge("宝鸡",100);
  72. gm.AddEdge("宝鸡",200);
  73. gm.AddEdge("咸阳",100);
  74. gm.PrintMaxtix();
  75. GraphMatrix<string,size_t> gm1(v,4,true);//有向图
  76. cout<<"有向图邻接矩阵:"<<endl;
  77. gm1.AddEdge("西安",7);
  78. gm1.AddEdge("西安",200);
  79. gm1.AddEdge("西安",500);
  80. gm1.AddEdge("宝鸡",100);
  81. gm1.AddEdge("宝鸡",200);
  82. gm1.AddEdge("咸阳",100);
  83. gm1.PrintMaxtix();
  84. }
邻接表及其遍历

  1. #include <iostream>
  2. #include <string>
  3. #include <vector>
  4. #include <queue>
  5. using namespace std;
  6. template<class V,class W>
  7. class GraphLink
  8. {
  9. struct Node
  10. {
  11. W _w;
  12. size_t _src;
  13. size_t _dst;
  14. Node* Next;
  15. Node(int src=0,int dst=0,const W& w=W())
  16. :_src(src),_dst(dst),_w(w),Next(NULL)
  17. {}
  18. };
  19. public:
  20. GraphLink(const V* vertex,int size,bool isDirection=false)
  21. :_isDirection(isDirection)
  22. {
  23. _vertex.resize(size);
  24. _table.resize(size);
  25. for(size_t i=0;i<size;i++)
  26. {
  27. _vertex[i]=vertex[i];
  28. }
  29. }
  30. int GetIndex(const V& v)
  31. {
  32. for (int i=0;i<_vertex.size();i++)
  33. {
  34. if(_vertex[i]==v)
  35. return i;
  36. }
  37. throw std::invalid_argument("顶点赋值错误");
  38. }
  39. void _AddEdge(size_t src,w);
  40. }
  41. }
  42. void DFS(const V& v)
  43. {
  44. vector<bool> visted(_vertex.size(),visted);
  45. }
  46. cur=cur->Next;
  47. }
  48. }
  49. void _BFS(size_t src,visted);
  50. }
  51. void PrintLink()
  52. {
  53. for (size_t i=0;i<_vertex.size();++i)
  54. {
  55. cout<<_vertex[i]<<"["<<i<<"]->";
  56. Node* cur=_table[i];
  57. while (cur)
  58. {
  59. cout<<_vertex[cur->_dst]<<" ["<<cur->_dst<<"]"<<cur->_w<<"->";
  60. cur=cur->Next;
  61. }
  62. cout<<"NULL"<<endl;
  63. }
  64. }
  65. protected:
  66. vector<V> _vertex;
  67. vector<Node*> _table;
  68. bool _isDirection;
  69. };
  70. void TestGraphLink()
  71. {
  72. string v[4]={"西安","延安"};
  73. GraphLink<string,4);//无向图邻接表
  74. cout<<"无向图邻接表:"<<endl;
  75. gm.AddEdge("西安",100);
  76. gm.PrintLink();
  77. cout<<"无向图DFS遍历:"<<endl;//深度优先遍历
  78. gm.DFS("西安");
  79. gm.DFS("宝鸡");
  80. gm.DFS("咸阳");
  81. gm.DFS("延安");
  82. cout<<"无向图BFS遍历:"<<endl;//广度优先遍历
  83. gm.BFS("西安");
  84. gm.BFS("宝鸡");
  85. gm.BFS("咸阳");
  86. gm.BFS("延安");
  87. GraphLink<string,true);//有向图邻接表
  88. cout<<"有向图邻接表:"<<endl;
  89. gm1.AddEdge("西安",100);
  90. gm1.PrintLink();
  91. cout<<"有向图DFS遍历:"<<endl;//深度优先遍历
  92. gm1.DFS("西安");
  93. gm1.DFS("宝鸡");
  94. gm1.DFS("咸阳");
  95. gm1.DFS("延安");
  96. cout<<"有向图BFS遍历:"<<endl;//广度优先遍历
  97. gm1.BFS("西安");
  98. gm1.BFS("宝鸡");
  99. gm1.BFS("咸阳");
  100. gm1.BFS("延安");
  101. }

测试代码

  1. #include "Graph.h"
  2. #include "GraphLink.h"
  3. #include<stdlib.h>
  4. int main()
  5. {
  6. TestGraphMatrix();
  7. TestGraphLink();
  8. system("pause");
  9. return 0;
  10. }
测试结果

猜你在找的数据结构相关文章