当前位置:   article > 正文

C/C++ 图---邻接矩阵存储,深度/广度优先遍历_邻接矩阵存储图的深度优先遍历

邻接矩阵存储图的深度优先遍历

  邻接矩阵--------是用一维数组存放顶点的信息,用二维数组存储边的信息.

1.先定义图的变量信息。

  1. #include<iostream>
  2. using namespace std;
  3. #include<queue>
  4. #define MaxSize 100
  5. typedef struct{
  6. int vertex[MaxSize]; //数组中存储节点的信息
  7. int arc[MaxSize][MaxSize]; //这个二维数组保存邻接矩阵
  8. int vertexnum; //记录图中节点个数
  9. int arcnum; // 记录图中边的个数
  10. }Graph;
  11. int visited[MaxSize]; //全局遍历,用于记录节点是否被访问过
  12. //当进行一次遍历后,visited[]数组的值就需要重新赋值, 否则再次遍历的时候visited[]数组就是之前的值,

2.图的创建

1)首先确定图的定点数n 和边数e;

2)图有4个信息分别是vertex[], arc[][], vertexnum, arcnum, 和一个全局变量visited[]数组。

对这几个信息分别初始化。

首先是vertex[]数组,这里面保存的是顶点信息,所以用arr[]数组赋值即可

arc[][]数组保存的是顶点间是否有边, 如arc[1][2]=1表示顶点1到顶点2两个顶点间有边。

vertexnum表示节点个数,用n赋值即可

arcnum表示边的个数,用e赋值即可。

注意,无向图,a->b有边,则b->a也有边,矩阵是对称的。

 

  1. void Creat_Graph(Graph &G, int n, int e, int arr[]) //要传入图G的引用。否则创建图不成功
  2. {
  3. G.vertexnum=n;
  4. G.arcnum=e;
  5. for(int i=0; i<G.vertexnum; i++) //把数组中的每个节点值保存在图中
  6. {
  7. G.vertex[i]=arr[i];
  8. }
  9. //让visited[i]数组值为0, 表示顶点i没有被访问。
  10. for(int i=0; i<G.vertexnum; i++)
  11. {
  12. visited[i]=0;
  13. }
  14. //初始化为0, 表示各个顶点之间,一开始都不存在边
  15. for(int i=0; i<G.vertexnum; i++)
  16. {
  17. for(int j=0; j<G.vertexnum; j++)
  18. {
  19. G.arc[i][j]=0;
  20. }
  21. }
  22. //开始生成图 无向图中,如果1->2有条边,则2->1也有条边,
  23. for(int i=0; i<G.arcnum; i++)
  24. {
  25. int a,b;
  26. cin>>a>>b;
  27. G.arc[a][b]=1;
  28. G.arc[b][a]=1;
  29. }
  30. }

深度优先遍历伪代码:

        1.访问顶点V, 设置visited[v]=1, 表示V顶点已经被访问过了

        2.w=顶点v的第一个邻接点,

        3. while(w存在 并且 未被访问时)

                3.1 以w为根节点, 递归访问w节点,直到没有邻接点后返回

  1. void DFSTraverse(Graph G, int v)
  2. {
  3. cout<<G.vertex[v];
  4. visited[v]=1;
  5. //每个顶点都可能与其余的n-1个顶点相连,所以每次以顶点v开始,都要遍历所有顶点
  6. for(int i=0; i<G.vertexnum; i++)
  7. {
  8. //G.arc[v][i]==1 表示顶点V到顶点i有一条边,
  9. //visited[i]==0 表示顶点i未被访问/
  10. if(G.arc[v][i]==1 && visited[i]==0)
  11. {
  12. DFSTraverse(G,i);
  13. }
  14. }
  15. }

广度优先伪代码:

        1.初始化队列Q

        2. 访问顶点V,设置visited[v]=1,并且将顶点V入队

        3.while(队列不为空)

                3.1  w=顶点v的第一个邻接点,

                while(w存在)

                        访问顶点w的邻接点 visited[w]=1

                        w的邻接点入队

                w=顶点v的下一个邻接点    

                直到顶点v的邻接点都访问完毕,退出内循环。

  1. void BFSTraverse(Graph G, int v, queue<int> Q)
  2. {
  3. cout<<G.vertex[v];
  4. visited[v]=1;
  5. Q.push(G.vertex[v]);
  6. while(!Q.empty())
  7. {
  8. int val = Q.front(); //队列是队头出队,队尾进队 这是访问头节点
  9. Q.pop(); //删除 头节点元素
  10. //弹出一个val节点后,要遍历所有节点,查看val和哪些节点有边且没被访问过。
  11. for(int i=0; i<G.vertexnum; i++)
  12. {
  13. if(G.arc[val][i]==1 && visited[i]==0)
  14. {
  15. cout<<G.vertex[i];
  16. visited[i]=1;
  17. Q.push(G.vertex[i]);
  18. }
  19. }
  20. }
  21. }

完整代码:

  1. //无向图创建与遍历
  2. #include<iostream>
  3. using namespace std;
  4. #include<queue>
  5. #define MaxSize 100
  6. typedef struct{
  7. int data;
  8. int vertex[MaxSize]; //数组中存储保存的节点值
  9. int arc[MaxSize][MaxSize]; //这个二维数组保存邻接矩阵
  10. int vertexnum; //记录图中节点个数
  11. int arcnum; // 记录图中边的个数
  12. }Graph;
  13. int visited[MaxSize]; //全局遍历,用于记录节点是否被访问过
  14. void DFSTraverse(Graph G, int v)
  15. {
  16. cout<<G.vertex[v];
  17. visited[v]=1;
  18. for(int i=0; i<G.vertexnum; i++)
  19. {
  20. if(G.arc[v][i]==1 && visited[i]==0) //arc[v][i]=1表示: 顶点v到邻接点i有边,且这个邻接点没有被访问过。 则深度优先递归访问这个邻接点。
  21. {
  22. DFSTraverse(G,i);
  23. }
  24. }
  25. }
  26. void BFSTraverse(Graph G, int v, queue<int> Q)
  27. {
  28. cout<<G.vertex[v];
  29. visited[v]=1;
  30. Q.push(G.vertex[v]);
  31. while(!Q.empty())
  32. {
  33. int val = Q.front(); //队列是队头出队,队尾进队
  34. Q.pop();
  35. for(int i=0; i<G.vertexnum; i++)
  36. {
  37. if(G.arc[val][i]==1 && visited[i]==0)
  38. {
  39. cout<<G.vertex[i];
  40. visited[i]=1;
  41. Q.push(G.vertex[i]);
  42. }
  43. }
  44. }
  45. }
  46. void Creat_Graph(Graph &G, int n, int e, int arr[]) //如果不是在类里面,要传入图G的引用。否则创建图不成功
  47. {
  48. G.vertexnum=n;
  49. G.arcnum=e;
  50. for(int i=0; i<G.vertexnum; i++) //把数组中的每个节点值保存在图中
  51. {
  52. G.vertex[i]=arr[i];
  53. }
  54. //让visited[]数组值为0, 表示没有被访问过。 **调用过一次深度遍历或广度遍历,都需要重新给visited赋值,
  55. // for(int i=0; i<G.vertexnum; i++)
  56. // {
  57. // visited[i]=0;
  58. // }
  59. for(int i=0; i<G.vertexnum; i++) //当有n的节点的时候, n*n的矩阵,初始值都为0,表示任何两个顶点之间都没边
  60. {
  61. for(int j=0; j<G.vertexnum; j++)
  62. {
  63. G.arc[i][j]=0;
  64. }
  65. }
  66. //开始生成边 无向图中,如果1->2有条边,则2->1也有条边,
  67. for(int i=0; i<G.arcnum; i++)
  68. {
  69. int a,b;
  70. cin>>a>>b;
  71. G.arc[a][b]=1;
  72. G.arc[b][a]=1;
  73. }
  74. }
  75. void set_visited(Graph G)
  76. {
  77. for(int i=0; i<G.vertexnum; i++)
  78. {
  79. visited[i]=0;
  80. }
  81. }
  82. int main()
  83. {
  84. queue<int> Q;
  85. int n,e; //n是节点数,e是边数
  86. Graph G;
  87. cin>>n>>e;
  88. int arr[n];
  89. for(int i=0; i<n; i++)
  90. {
  91. cin>>arr[i];
  92. }
  93. Creat_Graph(G,n,e,arr);
  94. set_visited(G);
  95. cout<<" DFSTraverse: ";
  96. DFSTraverse(G,0);
  97. set_visited(G);
  98. cout<<endl<<" BFSTraverse: ";
  99. BFSTraverse(G, 0, Q);
  100. return 0;
  101. }

练习:

输入:

5 7

0 1 2 3 4

0 1

0 3

0 4

1 2

1 4

2 3

3 4

输出:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/596647
推荐阅读
相关标签
  

闽ICP备14008679号