当前位置:   article > 正文

迪杰斯特拉(Dijkstra)算法求最短路径_基于dijsktra算法的最短路径求解

基于dijsktra算法的最短路径求解

1.Dijkstra算法原理

 

\begin{bmatrix} \infty & \infty & 10 & \infty & 30 & 100 \\ \infty & \infty & 5 & \infty & \infty & \infty \\ \infty & \infty & \infty & 50 & \infty & \infty \\ \infty & \infty & \infty & \infty & \infty & 10 \\ \infty & \infty & \infty & 20 & \infty & 60 \\ \infty & \infty & \infty & \infty & \infty & \infty \\ \end{bmatrix}

(1)两个顶点集 S 、T = V - S(V是原图所有顶点集合)

S:存放已找到最短路径的顶点

T:存放未找到最短路径的顶点

(2)实现步骤:

先将开始节点(V0)加入 S,不断从 T 中选取到 V0 有最短路径的顶点 (u),将 u 加入 S;S 中每加入一个顶点都要修改 V0 到 T 中剩余顶点的最短路径长度值。直到 T 中顶点全部加入 S。

终点V0 到各终点的 D 值和最短路径求解过程
i = 1i = 2i = 3i = 4i = 5
V1

D[1] = 

p[1] = {0,0,0,0,0,0}

V2

D[2] = 10

p[2] = {1,0,1,0,0,0}

即<V0,V2>

V3

D[3] = 

p[3] = {0,0,0,0,0,0}

D[3] = 60

p[3] = {1,0,1,1,0,0}

即<V0,V2,V3>

D[3] = 50

p[3] = {1,0,0,1,1,0}

即<V0,V4,V3>

V4

D[4] = 30

p[4] = {1,0,0,0,1,0}

即<V0,V4>

D[4] = 30

p[4] = {1,0,0,0,1,0}

即<V0,V4>

V5

D[5] = 100

p[5] = {1,0,0,0,0,1}

即<V0,V5>

D[5] = 100 

p[5] = {1,0,0,0,0,1}

即<V0,V5>

D[5] = 90

p[5] = {1,0,0,0,1,1}

即<V0,V4,V5>

D[5] = 60

p[5] = {1,0,0,1,1,1}

即<V0,V4,V3,V5>

VjV2V4V3V5
S{V0,V2}{V0,V2,V4}{V0,V2,V4,V3}{V0,V2,V4,V3,V5}

2.源代码

2.1 Java实现

  1. package math_problem;
  2. import java.util.Arrays;
  3. import java.util.Scanner;
  4. class Graph {
  5. static final int MAX_VEX_NUM = 20; // 最大顶点数
  6. char[] vertex = new char[MAX_VEX_NUM]; // 顶点数组
  7. int graphType; // 图的类型。1-有向图,0-无向图
  8. int vexNum; // 实际顶点数
  9. int edgeNum; // 实际边数
  10. int[][] edgeWeight = new int[MAX_VEX_NUM][MAX_VEX_NUM]; // 保存边的权值
  11. }
  12. public class ShortestPathDemo {
  13. static Scanner input = new Scanner(System.in);
  14. static final int INFINITY = 65535; // 边上最大权值
  15. private static int getIndexOfChar(char[] charArray, char c) {
  16. for (int i = 0; i < charArray.length; i++) {
  17. if (c == charArray[i])
  18. return i;
  19. }
  20. return -1;
  21. }
  22. private void createGraph(Graph g) {
  23. int weight;
  24. char sVex, eVex;// 边的起始、结束顶点
  25. System.out.print("创建图,请输入图的类型(1:有向图/0:无向图):");
  26. g.graphType = input.nextInt();
  27. System.out.println("创建图,请输入各顶点信息...");
  28. System.out.print("请输入顶点数量:");
  29. g.vexNum = input.nextInt();
  30. for (int l = 0; l < g.vexNum; l++) {
  31. System.out.printf("第 %d 个顶点:", l+1);
  32. g.vertex[l] = (input.next().toCharArray())[0];
  33. }
  34. System.out.println("创建图,请输入各边顶点及权值...");
  35. System.out.print("请输入边数量:");
  36. g.edgeNum = input.nextInt();
  37. // 初始化邻接矩阵
  38. for (int i = 0; i < g.vexNum; i++) {
  39. for (int j = 0; j < g.vexNum; j++) {
  40. g.edgeWeight[i][j] = INFINITY;
  41. }
  42. }
  43. System.out.println("请依次输入每条边的信息(起始顶点,结束顶点,权值):");
  44. int indexOfsVex, indexOfeVex;
  45. for (int i = 0; i < g.edgeNum; i++) {
  46. sVex = input.next().charAt(0);
  47. eVex = input.next().charAt(0);
  48. weight = input.nextInt();
  49. indexOfsVex = getIndexOfChar(g.vertex, sVex);
  50. indexOfeVex = getIndexOfChar(g.vertex, eVex);
  51. g.edgeWeight[indexOfsVex][indexOfeVex] = weight;
  52. // 若是无向图,保存边 E(k,j)的权值
  53. if (g.graphType == 0) {
  54. g.edgeWeight[indexOfeVex][indexOfsVex] = weight;
  55. }
  56. }
  57. }
  58. // 输出邻接矩阵
  59. private void displayAdjMatrix(Graph g) {
  60. int i, j;
  61. // 先输出顶点信息
  62. for (i = 0; i < g.vexNum; i++) {
  63. System.out.printf("\t%c", g.vertex[i]);
  64. }
  65. System.out.println();
  66. // 输出邻接矩阵
  67. for (j = 0; j < g.vexNum; j++) {
  68. System.out.printf("%c", g.vertex[j]);
  69. for (i = 0; i < g.vexNum; i++) {
  70. if (g.edgeWeight[j][i] == INFINITY) {
  71. // 权值大于等于最大权值时,输出无穷大的符号
  72. System.out.print("\t∞");
  73. continue;
  74. }
  75. System.out.printf("\t%d", g.edgeWeight[j][i]);
  76. }
  77. System.out.println();
  78. }
  79. }
  80. private static void dijkstraShortestPath(Graph g) {
  81. int minWeight, indexOfsVex, k = 0;
  82. char startVex;
  83. int[] d = new int[g.vexNum];
  84. int[] s = new int[g.vexNum];
  85. int[][] p = new int[g.vexNum][g.vexNum];
  86. System.out.print("请输入开始节点:");
  87. startVex = input.next().charAt(0);
  88. indexOfsVex = getIndexOfChar(g.vertex, startVex);
  89. for (int i = 0; i < g.vexNum; i++) {
  90. d[i] = g.edgeWeight[indexOfsVex][i];
  91. if (d[i] < INFINITY) {
  92. p[i][indexOfsVex] = 1;
  93. p[i][i] = 1;
  94. }
  95. }
  96. // 将起始节点加入集合 S
  97. s[indexOfsVex] = 1;
  98. for (int i = 1; i < g.vexNum; i++) {
  99. minWeight = INFINITY;
  100. for (int j = 0; j < g.vexNum; j++) {
  101. if (s[j] != 1 && d[j] < minWeight) {
  102. minWeight = d[j];
  103. k = j;
  104. }
  105. }
  106. // 将新的节点加入集合 S
  107. s[k] = 1;
  108. for (int j = 0; j < g.vexNum; j++) {
  109. if (s[j] != 1 && (minWeight + g.edgeWeight[k][j] < d[j])) {
  110. d[j] = minWeight + g.edgeWeight[k][j];
  111. for (int l = 0; l < g.vexNum; l++) {
  112. p[j][l] = p[k][l];
  113. }
  114. p[j][j] = 1;
  115. }
  116. }
  117. }
  118. for (int i = 0; i < g.vexNum; i++) {
  119. for (int j = 0; j < g.vexNum; j++) {
  120. System.out.print(p[i][j] + " ");
  121. }
  122. System.out.println();
  123. }
  124. System.out.println(Arrays.toString(d));
  125. }
  126. public static void main(String[] args) {
  127. Graph graph = new Graph();
  128. ShortestPathDemo demo = new ShortestPathDemo();
  129. demo.createGraph(graph);
  130. demo.displayAdjMatrix(graph);
  131. demo.dijkstraShortestPath(graph);
  132. }
  133. }
  1. 创建图,请输入图的类型(1:有向图/0:无向图):1
  2. 创建图,请输入各顶点信息...
  3. 请输入顶点数量:6
  4. 1 个顶点:0
  5. 2 个顶点:1
  6. 3 个顶点:2
  7. 4 个顶点:3
  8. 5 个顶点:4
  9. 6 个顶点:5
  10. 创建图,请输入各边顶点及权值...
  11. 请输入边数量:8
  12. 请依次输入每条边的信息(起始顶点,结束顶点,权值):
  13. 0 2 10
  14. 0 4 30
  15. 0 5 100
  16. 4 5 60
  17. 4 3 20
  18. 3 5 10
  19. 2 3 50
  20. 1 2 5
  21. 0 1 2 3 4 5
  22. 0 ∞ ∞ 1030 100
  23. 1 ∞ ∞ 5 ∞ ∞ ∞
  24. 2 ∞ ∞ ∞ 50 ∞ ∞
  25. 3 ∞ ∞ ∞ ∞ ∞ 10
  26. 4 ∞ ∞ ∞ 2060
  27. 5 ∞ ∞ ∞ ∞ ∞ ∞
  28. 请输入开始节点:0
  29. 0 0 0 0 0 0
  30. 0 0 0 0 0 0
  31. 1 0 1 0 0 0
  32. 1 0 0 1 1 0
  33. 1 0 0 0 1 0
  34. 1 0 0 1 1 1
  35. [65535, 65535, 10, 50, 30, 60]
  36. Process finished with exit code 0

2.2 C语言实现 

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define INFINITY 10000 /* 假定弧上权值无穷大时为10000 */
  4. #define MAX_VERTEX_NUM 100 /* 图中最大节点数 */
  5. typedef char VexType; /* 顶点类型设置为字符型 */
  6. typedef int weight; /* 弧上权值类型设置为整型 */
  7. typedef struct /* 弧表节点 */
  8. {
  9. VexType vex[MAX_VERTEX_NUM]; /* 图中节点 */
  10. weight edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM];/* 邻接矩阵 */
  11. int vexnum; /* 节点的数目 */
  12. int edgenum; /* 弧的数目 */
  13. }MGraph;
  14. void CreateDG(MGraph * DG); /* 邻接矩阵法创建有向图(directed graph) */
  15. void PrintDG(MGraph DG); /* 邻接矩阵形式输出图DG */
  16. void ShortestPath_Dijkstra(MGraph DG, VexType StartVex);
  17. /* 从节点StartVex开始求最短路径 */
  18. void locateVex(MGraph DG, VexType vex, int * index);
  19. /* 定位节点vex的下标并赋给index */
  20. int main(void)
  21. {
  22. MGraph g;
  23. CreateDG(&g);
  24. printf("------------------------------\n");
  25. printf("vexnum = %d ; edgenum = %d\n", g.vexnum, g.edgenum);
  26. printf("------------------------------\n");
  27. PrintDG(g);
  28. printf("------------------------------\n");
  29. ShortestPath_Dijkstra(g, '0');
  30. return 0;
  31. }
  32. void CreateDG(MGraph * DG)
  33. {
  34. int i = 0, j, k, w; /* w:权值 */
  35. char ch;
  36. printf("请依次输入顶点数、弧数:");
  37. scanf("%d %d", &(DG->vexnum), &(DG->edgenum));
  38. printf("请依次输入顶点(以回车结束输入):");
  39. getchar();
  40. while ((ch = getchar()) != '\n') /* 输入顶点信息 */
  41. DG->vex[i++] = ch;
  42. for (i = 0; i < DG->vexnum; i++) /* 初始化邻接矩阵 */
  43. for (j = 0; j < DG->vexnum; j++)
  44. DG->edges[i][j] = INFINITY;
  45. printf("顶点 | 下标\n");
  46. for (i = 0; i < DG->vexnum; i++) /* 显示图中顶点及其对应下标 */
  47. {
  48. printf("%3c%6d\n", DG->vex[i], i);
  49. }
  50. printf("请输入依次每条弧的弧尾下标(不带箭头)、弧头下标(带箭头)、权值(格式:i j w):\n");
  51. for (k = 0; k < DG->edgenum; k++) /* 建立邻接矩阵 */
  52. {
  53. scanf("\n%d%d%d", &i, &j, &w); /* 输入弧的两个节点及权值 */
  54. DG->edges[i][j] = w; /* 将矩阵对应位置元素置为权值 */
  55. }
  56. }
  57. void PrintDG(MGraph DG)
  58. {
  59. int i, j;
  60. for (i = 0; i < DG.vexnum; i++) /* 输出邻接矩阵 */
  61. {
  62. for (j = 0; j < DG.vexnum; j++)
  63. {
  64. if (DG.edges[i][j] == INFINITY) /* 节点不连通时,输出无穷大 */
  65. printf(" ∞");
  66. else /* 节点连通时,输出弧上权值 */
  67. printf("%5d", DG.edges[i][j]);
  68. }
  69. printf("\n");
  70. }
  71. }
  72. void ShortestPath_Dijkstra(MGraph DG, VexType StartVex)
  73. {
  74. int i, j, v, index; /* index:开始节点下标 */
  75. int min; /* 开始节点到指定节点的最短路径权值和 */
  76. int final[DG.vexnum]; /* 集合S,元素值为1:下标为i的节点以加入集合S;为0:未加入 */
  77. int P[DG.vexnum][DG.vexnum];/* 开始节点到各节点的最短路径 */
  78. int D[DG.vexnum]; /* 开始节点到下标为i的节点的最短路径权值之和 */
  79. locateVex(DG, StartVex, &index);
  80. for (i = 0; i < DG.vexnum; i++)
  81. {
  82. final[i] = 0; /* 初始化,刚开始集合S为空 */
  83. D[i] = DG.edges[index][i];
  84. for (j = 0; j < DG.vexnum; j++) /* 初始化路径,假设所有节点都不连通 */
  85. P[i][j] = 0;
  86. if (D[i] < INFINITY) /* 若节点连通,则在数组P[i]中标明路径 */
  87. {
  88. P[i][index] = 1;
  89. P[i][i] = 1;
  90. }
  91. }
  92. D[index] = 0; final[index] = 1; /* 开始节点加入S集 */
  93. for (i = 1; i < DG.vexnum; i++)
  94. {
  95. min = INFINITY;
  96. for (j = 0; j < DG.vexnum; j++)
  97. if (!final[j])
  98. if (D[j] < min) { v = j; min = D[j]; }
  99. final[v] = 1; /* 把离StartVex最近的下标为v的节点加入S */
  100. for (j = 0; j < DG.vexnum; j++)
  101. if (!final[j] && (min + DG.edges[v][j] < D[j]))
  102. {/* 若下标为j的节点为加入S且有更短路径,则更新D[j]和最短路径 */
  103. D[j] = min + DG.edges[v][j];
  104. for (int k = 0; k < DG.vexnum; k++)
  105. P[j][k] = P[v][k];
  106. P[j][j] = 1;
  107. }
  108. }
  109. printf("节点 %c 到各节点的最短路径:\n", StartVex);
  110. for (i = 0; i < DG.vexnum; i++)
  111. {
  112. for (j = 0; j < DG.vexnum; j++)
  113. printf("%5d", P[i][j]);
  114. printf("\n");
  115. }
  116. printf("节点 %c 到各节点的最短路径值:", StartVex);
  117. for (i = 0; i < DG.vexnum; i++)
  118. {
  119. if (D[i] == INFINITY)
  120. printf("∞, ");
  121. else
  122. printf("%d, ", D[i]);
  123. }
  124. }
  125. void locateVex(MGraph DG, VexType vex, int * index)
  126. {
  127. int i;
  128. for (i = 0; i < DG.vexnum; i++)
  129. {
  130. if (DG.vex[i] == vex)
  131. {
  132. *index = i;
  133. return;
  134. }
  135. }
  136. printf("节点定位失败!\n");
  137. }

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

闽ICP备14008679号