原博:https://blog.csdn.net/qq_35644234/article/details/60870719

Dijkstra.h

  1. /************************************************************/
  2. /* 程序作者:Willam */
  3. /* 程序完成时间:2017/3/8 */
  4. /* 有任何问题请联系:2930526477@qq.com */
  5. /************************************************************/
  6. //@尽量写出完美的程序
  7. #pragma once
  8. //#pragma once是一个比较常用的C/C++杂注,
  9. //只要在头文件的最开始加入这条杂注,
  10. //就能够保证头文件只被编译一次。
  11. #include<iostream>
  12. #include<string>
  13. using namespace std;
  14. /*
  15. 本程序是使用Dijkstra算法实现求解最短路径的问题
  16. 采用的邻接矩阵来存储图
  17. */
  18. //记录起点到每个顶点的最短路径的信息
  19. struct Dis {
  20. string path;
  21. int value;
  22. bool visit;
  23. Dis() {
  24. visit = false;
  25. value = 0;
  26. path = "";
  27. }
  28. };
  29. class Graph_DG {
  30. private:
  31. int vexnum; //图的顶点个数
  32. int edge; //图的边数
  33. int **arc; //邻接矩阵
  34. Dis * dis; //记录各个顶点最短路径的信息
  35. public:
  36. //构造函数
  37. Graph_DG(int vexnum, int edge);
  38. //析构函数
  39. ~Graph_DG();
  40. // 判断我们每次输入的的边的信息是否合法
  41. //顶点从1开始编号
  42. bool check_edge_value(int start, int end, int weight);
  43. //创建图
  44. void createGraph();
  45. //打印邻接矩阵
  46. void print();
  47. //求最短路径
  48. void Dijkstra(int begin);
  49. //打印最短路径
  50. void print_path(int);
  51. };

Dijkstra.cpp

  1. #include"Dijkstra.h"
  2. //构造函数
  3. Graph_DG::Graph_DG(int vexnum, int edge) {
  4. //初始化顶点数和边数
  5. this->vexnum = vexnum;
  6. this->edge = edge;
  7. //为邻接矩阵开辟空间和赋初值
  8. arc = new int*[this->vexnum];
  9. dis = new Dis[this->vexnum];
  10. for (int i = 0; i < this->vexnum; i++) {
  11. arc[i] = new int[this->vexnum];
  12. for (int k = 0; k < this->vexnum; k++) {
  13. //邻接矩阵初始化为无穷大
  14. arc[i][k] = INT_MAX;
  15. }
  16. }
  17. }
  18. //析构函数
  19. Graph_DG::~Graph_DG() {
  20. delete[] dis;
  21. for (int i = 0; i < this->vexnum; i++) {
  22. delete this->arc[i];
  23. }
  24. delete arc;
  25. }
  26. // 判断我们每次输入的的边的信息是否合法
  27. //顶点从1开始编号
  28. bool Graph_DG::check_edge_value(int start, int end, int weight) {
  29. if (start<1 || end<1 || start>vexnum || end>vexnum || weight < 0) {
  30. return false;
  31. }
  32. return true;
  33. }
  34. void Graph_DG::createGraph() {
  35. cout << "请输入每条边的起点和终点(顶点编号从1开始)以及其权重" << endl;
  36. int start;
  37. int end;
  38. int weight;
  39. int count = 0;
  40. while (count != this->edge) {
  41. cin >> start >> end >> weight;
  42. //首先判断边的信息是否合法
  43. while (!this->check_edge_value(start, end, weight)) {
  44. cout << "输入的边的信息不合法,请重新输入" << endl;
  45. cin >> start >> end >> weight;
  46. }
  47. //对邻接矩阵对应上的点赋值
  48. arc[start - 1][end - 1] = weight;
  49. //无向图添加上这行代码
  50. //arc[end - 1][start - 1] = weight;
  51. ++count;
  52. }
  53. }
  54. void Graph_DG::print() {
  55. cout << "图的邻接矩阵为:" << endl;
  56. int count_row = 0; //打印行的标签
  57. int count_col = 0; //打印列的标签
  58. //开始打印
  59. while (count_row != this->vexnum) {
  60. count_col = 0;
  61. while (count_col != this->vexnum) {
  62. if (arc[count_row][count_col] == INT_MAX)
  63. cout << "∞" << " ";
  64. else
  65. cout << arc[count_row][count_col] << " ";
  66. ++count_col;
  67. }
  68. cout << endl;
  69. ++count_row;
  70. }
  71. }
  72. void Graph_DG::Dijkstra(int begin){
  73. //首先初始化我们的dis数组
  74. int i;
  75. for (i = 0; i < this->vexnum; i++) {
  76. //设置当前的路径
  77. dis[i].path = "v" + to_string(begin) + "-->v" + to_string(i + 1);
  78. dis[i].value = arc[begin - 1][i];
  79. }
  80. //设置起点的到起点的路径为0
  81. dis[begin - 1].value = 0;
  82. dis[begin - 1].visit = true;
  83. int count = 1;
  84. //计算剩余的顶点的最短路径(剩余this->vexnum-1个顶点)
  85. while (count != this->vexnum) {
  86. //temp用于保存当前dis数组中最小的那个下标
  87. //min记录的当前的最小值
  88. int temp=0;
  89. int min = INT_MAX;
  90. for (i = 0; i < this->vexnum; i++) {
  91. if (!dis[i].visit && dis[i].value<min) {
  92. min = dis[i].value;
  93. temp = i;
  94. }
  95. }
  96. //cout << temp + 1 << " "<<min << endl;
  97. //把temp对应的顶点加入到已经找到的最短路径的集合中
  98. dis[temp].visit = true;
  99. ++count;
  100. for (i = 0; i < this->vexnum; i++) {
  101. //注意这里的条件arc[temp][i]!=INT_MAX必须加,不然会出现溢出,从而造成程序异常
  102. if (!dis[i].visit && arc[temp][i]!=INT_MAX && (dis[temp].value + arc[temp][i]) < dis[i].value) {
  103. //如果新得到的边可以影响其他为访问的顶点,那就就更新它的最短路径和长度
  104. dis[i].value = dis[temp].value + arc[temp][i];
  105. dis[i].path = dis[temp].path + "-->v" + to_string(i + 1);
  106. }
  107. }
  108. }
  109. }
  110. void Graph_DG::print_path(int begin) {
  111. string str;
  112. str = "v" + to_string(begin);
  113. cout << "以"<<str<<"为起点的图的最短路径为:" << endl;
  114. for (int i = 0; i != this->vexnum; i++) {
  115. if(dis[i].value!=INT_MAX)
  116. cout << dis[i].path << "=" << dis[i].value << endl;
  117. else {
  118. cout << dis[i].path << "是无最短路径的" << endl;
  119. }
  120. }
  121. }

main.cpp

  1. #include"Dijkstra.h"
  2. //检验输入边数和顶点数的值是否有效,可以自己推算为啥:
  3. //顶点数和边数的关系是:((Vexnum*(Vexnum - 1)) / 2) < edge
  4. bool check(int Vexnum, int edge) {
  5. if (Vexnum <= 0 || edge <= 0 || ((Vexnum*(Vexnum - 1)) / 2) < edge)
  6. return false;
  7. return true;
  8. }
  9. int main() {
  10. int vexnum; int edge;
  11. cout << "输入图的顶点个数和边的条数:" << endl;
  12. cin >> vexnum >> edge;
  13. while (!check(vexnum, edge)) {
  14. cout << "输入的数值不合法,请重新输入" << endl;
  15. cin >> vexnum >> edge;
  16. }
  17. Graph_DG graph(vexnum, edge);
  18. graph.createGraph();
  19. graph.print();
  20. graph.Dijkstra(1);
  21. graph.print_path(1);
  22. system("pause");
  23. return 0;
  24. }