1. /*
    2. Dijkstra 算法:
    3. 其实该算法和prim算法相似,不同的仅仅是更新那一块
    4. 我们这里仍然需要用到一个标记数组flag,用于记录顶点是否已被访问,一个路径数组dist,用于记录
    5. 目前到达各顶点的距离,此外我们还需要一个前置顶点数组prevs,用于存储路径
    6. */
    7. #define MAXSIZE 100 //数组最大值
    8. #define _CRT_SECURE_NO_WARNINGS
    9. #include <stdio.h>
    10. #include <stdlib.h>
    11. typedef struct Graph {
    12. int Vertex[MAXSIZE];
    13. int Edge[MAXSIZE][MAXSIZE];
    14. int numV, numE;//顶点、边数量
    15. }adjMatrix;
    16. void dijkstra(adjMatrix *G, int start) {
    17. int flag[MAXSIZE];//标记数组
    18. //int preV=0;//设置preV最开始为0
    19. int dist[MAXSIZE];//可到达顶点的距离数据
    20. int prevs[MAXSIZE];//存储每个顶点的前驱,也就是存储路径
    21. int k = start;
    22. for (int i = 0; i < G->numV; i++) {
    23. dist[i] = G->Edge[start][i];//初始化start到各顶点的距离
    24. prevs[i] = 0;//初始化
    25. flag[i] = 0;
    26. }
    27. flag[0] = 1;//传入的顶点设为已访问
    28. for (int i = 0; i < G->numV; i++) {//共进行G->numV次循环
    29. if (start == i)//是本身,不做操作
    30. continue;
    31. int min = 32767;
    32. //找目前能到达的权值最小顶点
    33. for (int j = 0; j < G->numV; j++) {
    34. if (!flag[j] && dist[j] < min) {//dist不为0代表未访问过
    35. min = dist[j];
    36. k = j;
    37. }
    38. }
    39. flag[k] = 1;
    40. //当我们加入新顶点时,我们要判断加入新顶点后是否路径会缩短,如果有这种情况,就要更新dist
    41. for (int m = 0; m < G->numV; m++) {
    42. if (!flag[m] && dist[m] > G->Edge[k][m] + dist[k]) {//当前 记录的从源点到k的距离 大于 加入k后的距离,进行更新!!
    43. dist[m] = G->Edge[k][m] + dist[k];
    44. prevs[m] = k;//一旦发生更换将m处的值设为k,代表由k处的顶点指向m处的顶点目前最近,即k是m的前驱
    45. }
    46. }
    47. }
    48. for (int i = 0; i < G->numV; i++) {
    49. i == start ? printf("%d ", 0) : printf("%d ", G->Vertex[prevs[i]]-48);
    50. }
    51. printf("\n");
    52. for (int i = 0; i < G->numV; i++) {
    53. printf("%d ", dist[i]);
    54. }
    55. }
    56. int main() {
    57. void createGraphFromFile(adjMatrix *);
    58. void dispGraph(adjMatrix *G);
    59. adjMatrix *G = (adjMatrix *)malloc(sizeof(adjMatrix));
    60. createGraphFromFile(G);
    61. dispGraph(G);
    62. dijkstra(G, 0);
    63. return 0;
    64. }
    1. /*
    2. Dijkstra 算法(图用邻接表实现):
    3. 其实该算法和prim算法相似,不同的仅仅是更新那一块
    4. 我们这里仍然需要用到一个标记数组flag,用于记录顶点是否已被访问,一个路径数组dist,用于记录
    5. 目前到达各顶点的距离,此外我们还需要一个前置顶点数组prevs,用于存储路径
    6. */
    7. #define MAXSIZE 100 //数组最大值
    8. #define _CRT_SECURE_NO_WARNINGS
    9. #include <stdio.h>
    10. #include <stdlib.h>
    11. #define MAXSIZE 100
    12. #define TYPE int
    13. typedef struct EdgeNode {//边表结点
    14. int index;//该边所指向的顶点的位置
    15. int weight;//权值
    16. EdgeNode *next;//下一个邻接边
    17. }EdgeNode;
    18. typedef struct VertexNode {//顶点表节点
    19. char info;//顶点信息
    20. EdgeNode *firstEdge;//指向第一条依附该顶点的边的指针
    21. }VertexNode, Adjlist[MAXSIZE];
    22. typedef struct {
    23. Adjlist adjlist;//顶点数组
    24. int numE, numV;//边数、顶点数
    25. }ALGraph;
    26. int getWeiFromAtoB(ALGraph *G, int a, int b) {//在图中获取a 到 b的距离(权值)
    27. for (EdgeNode *p = G->adjlist[a].firstEdge; p; p = p->next) {
    28. if (p->index == b) {//有直接连接,返回权值
    29. return p->weight;
    30. }
    31. }
    32. return 32767;//若没有直接连接,返回最大值
    33. }
    34. void dijkstra(ALGraph *G, int start) {
    35. int flag[100];//标记数组
    36. int preV=0;//设置preV最开始为0
    37. int dist[100];//可到达顶点的距离数据
    38. int prevs[100];//存储每个顶点的前驱,也就是存储路径
    39. int k = start;
    40. for (int i = 0; i < G->numV; i++) {
    41. dist[i] = 32767;//把所有值设为无穷
    42. }
    43. for (EdgeNode *p = G->adjlist[start].firstEdge; p; p = p->next) {
    44. dist[p->index] = p->weight;//把当前传入顶点的所有连接顶点的边的权值存入
    45. }
    46. for (int i = 0; i < G->numV;i++) {
    47. prevs[i] = 0;//初始化
    48. flag[i] = 0;
    49. }
    50. flag[0] = 1;//传入顶点设为已访问
    51. for (int i = 0; i < G->numV;i++) {//共进行G->numV次循环
    52. if (start == i)//是本身,不做操作
    53. continue;
    54. int min = 32767;
    55. //找目前能到达的权值最小顶点
    56. for (int j = 0; j < G->numV;j++) {
    57. if (!flag[j]&&dist[j]<min) {//dist不为0代表未访问过
    58. min = dist[j];
    59. k = j;
    60. }
    61. }
    62. flag[k]=1;
    63. //当我们加入新顶点时,我们要判断加入新顶点后是否路径会缩短,如果有这种情况,就要更新dist
    64. for (int m = 0; m < G->numV; m++) {
    65. int weight = getWeiFromAtoB(G, k, m);
    66. if (!flag[m]&&dist[m]> weight +dist[k]) {//当前 记录的从源点到k的距离 大于 加入k后的距离,进行更新!!
    67. dist[m] = weight + dist[k];
    68. prevs[m] = k;//一旦发生更换将m处的值设为k,代表由k处的顶点指向m处的顶点目前最近,即k是m的前驱
    69. }
    70. }
    71. }
    72. for (int i = 0; i < G->numV;i++) {
    73. printf("%c ",G->adjlist[prevs[i]].info);
    74. }
    75. }
    76. int main() {
    77. ALGraph *G = (ALGraph *)malloc(sizeof(ALGraph *));
    78. void createGraphInFile(ALGraph *);
    79. void dispGraph(ALGraph *);
    80. createGraphInFile(G);//创建图
    81. dispGraph(G);
    82. dijkstra(G, 0);
    83. return 0;
    84. }