Dijkstra算法c语言实现

Dijkstra算法

1.定义概览

Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点(节点需为源点)到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法是很有代表性的最短路径算法,注意该算法要求图中不存在负权边。

 实例:假设有A,B,C,D四个城市,(这里讨论的是有向网) 它们的距离为:  A->B(10),A->C(11),B->D(12),C->D(13);

所谓単源路径就是解决从源点 A开始找出到其他城市的最短距离(除本身外的其他所有城市)。Dijkstra算法可以求出A->B(10),A->C(11),A->D(22);

拓展2:多源最短路径(常用Floyd算法)是解决任意两点间的最短路径的一种算法,(不局限于从源点出发,到其他各个顶点 )可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd算法的时间复杂度为O(N3),空间复杂度为O(N2)。

代码

[cpp]  view plain  copy
  1. /* 
  2.   @ Dijkstra算法(単源最短路径) 
  3. */  
  4. #include<iostream>  
  5. #include<cstdio>  
  6. #include<cstdlib>  
  7. #define MAXV 100  
  8. #define LIMITLESS 9999    //定义为无穷大,默认为节点间不存在联系  
  9. using namespace std;  
  10. typedef struct  
  11. {  
  12.    char info; //顶点其他信息  
  13. }VertexType;  
  14.   
  15. typedef struct MGraph  
  16. {  
  17.     int v;     //顶点数  
  18.     int e;    //边数  
  19.     int edges[MAXV][MAXV];//邻接矩阵的数组表现  
  20.     VertexType vexs[MAXV]; //顶点信息  
  21. }MGraph;  
  22.   
  23. void creat(MGraph *G)  
  24. {  
  25.     int i, j, k, w;  
  26.     int start, end;  
  27.     printf("请输入顶点数和边数:\n");  
  28.     scanf("%d%d", &(G->v), &(G->e));  
  29.     getchar();  
  30.     printf("请输入顶点信息:\n");  
  31.     for (i = 0; i<G->v; i++)  
  32.     {  
  33.         scanf("%c", &(G->vexs[i].info));  
  34.     }  
  35.     for (i = 0; i<G->v; i++)  
  36.     {  
  37.         for (j = 0; j<G->v; j++)  
  38.         {  
  39.             G->edges[i][j] = LIMITLESS;  
  40.         }  
  41.     }  
  42.     printf("输入图的顶点边的下标值和它的权值:\n");  
  43.     for (k = 0; k<G->e; k++)  
  44.     {  
  45.         scanf("%d%d%d", &start, &end, &w);  
  46.         G->edges[start][end] = w;  
  47.     }  
  48. }  
  49.   
  50. void print(MGraph *G)  
  51. {  
  52.     int i, j;  
  53.     printf("顶点数:%d,边数:%d\n", G->v, G->e);  
  54.     printf("%d个顶点的信息:\n", G->v);  
  55.     for (i = 0; i<G->v; i++)  
  56.     {  
  57.         printf("%5c",G->vexs[i].info);  
  58.     }  
  59.     printf("\n各个顶点的连接情况:\n");  
  60.     printf("\t");  
  61.     for (i = 0; i<G->v; i++)  
  62.     {  
  63.         printf("[%d]\t", i);  
  64.     }  
  65.     printf("\n");  
  66.     for (i = 0; i<G->v; i++)  
  67.     {  
  68.         printf("[%d]\t", i);  
  69.         for (j = 0; j<G->v; j++)  
  70.         {  
  71.             if (G->edges[i][j] == LIMITLESS)  
  72.             {  
  73.                 printf("oo\t");  
  74.             }  
  75.             else  
  76.             {  
  77.                 printf("%d\t", G->edges[i][j]);  
  78.             }  
  79.         }  
  80.         printf("\n");  
  81.     }  
  82. }  
  83.   
  84. void Ppath(MGraph *g,int path[], int i, int v) //前向递归查找路径上的顶点,但不包含起点与终点的路径值  
  85. {  
  86.     int k;  
  87.     k = path[i];  
  88.     if (k == v)   //无中间节点,退出  
  89.     {  
  90.         return;  
  91.     }  
  92.     Ppath(g,path, k, v);  
  93.     printf("%c",g->vexs[k]);  
  94. }  
  95.   
  96. void Dispath(MGraph *g,int dist[], int path[], int s[], int n, int v)  
  97. {  
  98.     int i;  
  99.     for (i = 0; i < n; i++)  
  100.     {  
  101.         if (s[i] == 1)  
  102.         {  
  103.             printf("从%c到%c的最短路径长度为:%d\t路径为:", g->vexs[v], g->vexs[i], dist[i]);  
  104.             printf("%c",g->vexs[v]);     //输出路径上的起点  
  105.             Ppath(g,path, i, v);  //输出路径上的中间点  
  106.             printf("%c\n",g->vexs[i]); //输出路径上的终点  
  107.         }  
  108.         else  
  109.         {  
  110.             printf("从%c到%c不存在路径\n", g->vexs[v], g->vexs[i]);  
  111.         }  
  112.     }  
  113. }  
  114.   
  115. void Dijkstra(MGraph *g, int v)  
  116. {  
  117.     int mindis, i, j, u;  
  118.     int s[MAXV];     //表示这个顶点是否存入最短路线中(0表示未加入,1表示已加入)  
  119.     int dist[MAXV]; //表示起始点到此顶点的距离  
  120.     int path[MAXV];//表示此点的上一步是哪一个顶点  
  121.     for (i = 0; i < g->v; i++)  
  122.     {  
  123.         s[i] = 0;  
  124.         dist[i] = g->edges[v][i];  
  125.         if (g->edges[v][i] < LIMITLESS)  
  126.         {  
  127.             path[i] = v;  
  128.         }  
  129.         else  
  130.         {  
  131.             path[i] = -1;  
  132.         }  
  133.     }  
  134.     s[v] = 1;  
  135.     path[v] = 0;  
  136.     for (i = 0; i < g->v; i++)  
  137.     {  
  138.         mindis = LIMITLESS;         //mindis置最小长度初值  
  139.         for (j = 0; j < g->v; j++) //选取不在s中且具有最小距离的顶点u  
  140.         {  
  141.             if (s[j] == 0 && dist[j] <mindis)  
  142.             {  
  143.                 mindis = dist[j];  
  144.                 u = j;  
  145.             }  
  146.         }  
  147.         s[u] = 1;  
  148.         for (j = 0; j < g->v; j++)  
  149.         {  
  150.             if (s[j] == 0)  
  151.             {  
  152.                 if (g->edges[u][j] < LIMITLESS&&dist[u] + g->edges[u][j] < dist[j])  
  153.                 {  
  154.                     dist[j] = dist[u] + g->edges[u][j];  
  155.                     path[j] = u;  
  156.                 }  
  157.             }  
  158.         }  
  159.     }  
  160.     Dispath(g ,dist, path, s, g->v, v);  
  161. }  
  162.   
  163. int main(void)  
  164. {  
  165.     MGraph *g;  
  166.     g = (MGraph *)malloc(sizeof(MGraph));  
  167.     creat(g);  
  168.     print(g);  
  169.     Dijkstra(g,0);  
  170.     return 0;  
  171. }  
  172.    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值