图的最短路径之Dijkstra算法C/C++代码实现

朴灿烈づ我的快乐病毒、 2023-02-19 14:27 93阅读 0赞

迪杰斯特拉Dijkstra算法:

该算法用来求解从某个源点到其余各顶点的最短路径

以该图为例:
在这里插入图片描述
其邻接矩阵为:
在这里插入图片描述
最短路径为:
在这里插入图片描述

具体过程:

算法中用到了三个辅组数组:
S[i]:布尔值记录到顶点最短路径是否已经被确定
Path[i]:记录顶点最短路径的直接前驱顶点序号
D[i]:记录最短路径的长度,初值为权值
在这里插入图片描述
(上表中的i表示循环次数)

每次从D数组中选择最小的加入到S集合,紧接着用刚加入的顶点和个顶点比较如果路径变小了则更新相应D数组

代码如下:

  1. #include<stdio.h>
  2. #define MaxInt 999 //定义无穷大
  3. #define MVNum 100
  4. typedef char VerTexType; //顶点类型
  5. typedef int ArcType; //边权值类型
  6. //邻接矩阵存储结构
  7. typedef struct
  8. {
  9. VerTexType vexs[MVNum]; //顶点表
  10. ArcType arcs[MVNum][MVNum]; //邻接矩阵
  11. int vexnum, arcnum; //图的当前点数和边数
  12. }AMGraph;
  13. void printGraph(AMGraph G);
  14. int LocateVex(AMGraph G, char v);
  15. //创建有向网
  16. void CreateUDN(AMGraph &G)
  17. {
  18. G.vexnum = 6; //输入总顶点数和边数
  19. G.arcnum = 8;
  20. G.vexs[0] = 'v0'; //输入顶点信息
  21. G.vexs[1] = 'v1';
  22. G.vexs[2] = 'v2';
  23. G.vexs[3] = 'v3';
  24. G.vexs[4] = 'v4';
  25. G.vexs[5] = 'v5';
  26. for (int i = 0; i < G.vexnum; i++) //初始化邻接矩阵为极大值
  27. {
  28. for (int j = 0; j < G.vexnum; j++)
  29. {
  30. G.arcs[i][j] = MaxInt;
  31. }
  32. }
  33. //输入权值
  34. int i, j;
  35. i = LocateVex(G, 'v0');
  36. j = LocateVex(G, 'v2');
  37. G.arcs[i][j] = 10;
  38. i = LocateVex(G, 'v0');
  39. j = LocateVex(G, 'v4');
  40. G.arcs[i][j] = 30;
  41. i = LocateVex(G, 'v0');
  42. j = LocateVex(G, 'v5');
  43. G.arcs[i][j] = 100;
  44. i = LocateVex(G, 'v1');
  45. j = LocateVex(G, 'v2');
  46. G.arcs[i][j] = 5;
  47. i = LocateVex(G, 'v2');
  48. j = LocateVex(G, 'v3');
  49. G.arcs[i][j] = 50;
  50. i = LocateVex(G, 'v3');
  51. j = LocateVex(G, 'v5');
  52. G.arcs[i][j] = 10;
  53. i = LocateVex(G, 'v4');
  54. j = LocateVex(G, 'v3');
  55. G.arcs[i][j] = 20;
  56. i = LocateVex(G, 'v4');
  57. j = LocateVex(G, 'v5');
  58. G.arcs[i][j] = 60;
  59. printGraph(G);
  60. }
  61. //返回顶点在数组中的下标
  62. int LocateVex(AMGraph G, char v)
  63. {
  64. for (int i = 0; i < G.vexnum; i++)
  65. {
  66. if (G.vexs[i] == v)
  67. {
  68. return i;
  69. }
  70. }
  71. }
  72. //打印输出邻接矩阵
  73. void printGraph(AMGraph G)
  74. {
  75. for (int i = 0; i < G.vexnum; i++)
  76. {
  77. printf("v%d :", i + 1);
  78. for (int j = 0; j < G.vexnum; j++)
  79. {
  80. printf("%5d ", G.arcs[i][j]);
  81. }
  82. printf("\n");
  83. }
  84. }
  85. //邻接矩阵深度优先遍历
  86. bool visited[MVNum];
  87. void DFS_AM(AMGraph G, int v)
  88. {
  89. printf("v%c->", G.vexs[v]);
  90. visited[v] = true;
  91. for (int w = 0; w < G.vexnum; w++)
  92. {
  93. if ((G.arcs[v][w]) != 0 && (!visited[w]))
  94. {
  95. DFS_AM(G, w);
  96. }
  97. }
  98. }
  99. //最短路径迪杰斯特拉算法
  100. bool S[MVNum]; //判断v0到vi是否已经被确定最短路径长度
  101. int D[MVNum]; //存放v0到vi的最短路径长度值
  102. int Path[MVNum]; //存放vi的直接前驱顶点序号
  103. void ShortestPath_DIJ(AMGraph G, int v0)
  104. {
  105. //初始化
  106. int n = G.vexnum; //图的顶点数
  107. for (int v = 0; v< n; v++)
  108. {
  109. S[v] = false;
  110. D[v] = G.arcs[v0][v];
  111. if (D[v]<MaxInt) //如果v0到v有路径,则Path数组置为v0
  112. {
  113. Path[v] = v0;
  114. }
  115. else {
  116. //否则置为-1
  117. Path[v] = -1;
  118. }
  119. }
  120. S[v0] = true;
  121. D[v0] = 0;
  122. //算法开始
  123. for (int i = 1; i < n; i++)
  124. {
  125. int min = MaxInt;
  126. int v = 0;
  127. //查找D[]中权值最小的且加入到完成集合S
  128. for (int w = 0; w <n; w++)
  129. {
  130. if (!S[w] && D[w] < min)
  131. {
  132. v = w; //最小的序号存入v中
  133. min = D[w]; //最小权值存入min
  134. }
  135. }
  136. S[v] = true;
  137. //完成集合S添加新顶点后更新最短路径信息
  138. for (int w = 0; w < n; w++)
  139. {
  140. if (!S[w] && (D[v] + G.arcs[v][w] < D[w]))
  141. {
  142. D[w] = D[v] + G.arcs[v][w];
  143. Path[w] = v;
  144. }
  145. }
  146. //逆序输出最短路径
  147. int t = v;
  148. while (Path[t] != -1)
  149. {
  150. printf("v%c<— ", G.vexs[t]);
  151. t = Path[t];
  152. }
  153. printf("v0\n");
  154. }
  155. }
  156. int main()
  157. {
  158. AMGraph G;
  159. CreateUDN(G);
  160. int v = 0;
  161. printf("深度优先遍历::");
  162. DFS_AM(G, v);
  163. int v0 = 0;
  164. printf("\n====================================\n");
  165. printf("v0到各顶点的最短路径:\n");
  166. ShortestPath_DIJ(G, v0);
  167. }

运行结果:

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,93人围观)

还没有评论,来说两句吧...

相关阅读

    相关 路径Dijkstra算法

    最短路径之Dijkstra算法(看到i,j,k三个变量可以理解为需要三个for循环,方便记忆) 本节来学习指定一个点(源点)到其余各个顶点的最短路径,也称为”单源最短路径”。