Dijkstra 算法总结

举报
Linux猿 发表于 2021/08/06 01:13:12 2021/08/06
【摘要】 Dijkstra算法思想:             Dijkstra算法又称单源最短路,求一个点到图中其它点的最短路。            假设有两个集合 S 和...

Dijkstra算法思想:

            Dijkstra算法又称单源最短路,求一个点到图中其它点的最短路。

           假设有两个集合 S 和 T ,S中只包含源点,T中包含除源点外的其它点,开始寻找由源点出发到 T 中点的距离最小的点,让它加入 S 中,然后以加入的点为中间点更新 T 中点到源点的距离(如果源点到中间点的距离加上中间点到 T 中与中间点有关系的点的距离小于源点到有关系的点的距离,就更新有关系的点到源点的距离)然后继续在 T 中寻找到 S 中距离最短的点,重复上述操作,一直找完所有点。

 如图:

(1)开始时,s1={v0},s2={v1,v2,v3,v4},v0到各点的最短路径是{0,10,&,30,100};
(2)在还未进入s1的顶点之中,最短路径为v1,因此s1={v0,v1},由于v1到v2有路径,因此v0到各点的最短路径更新为{0,10,60,30,100};
(3)在还未进入s1的顶点之中,最短路径为v3,因此s1={v0,v1,v3},由于v3到v2、v4有路径,因此v0到各点的最短路径更新为{0,10,50,30,90};
(4)在还未进入s1的顶点之中,最短路径为v2,因此s1={v0,v1,v3,v2},由于v2到v4有路径,因此v0到各点的最短路径更新为{0,10,50,30,60};
数据结构:
(1)用一个二维数组a[i..j,i..j]来存储各点之间的距离,10000表示无通路:
(2)用数组dist[i..j]表示最短路径;
(3)用集合s表示找到最短路径的结点

代码(模版):  


  
  1. memset(vis,0,sizeof(vis));
  2. for(i=1;i<n;i++)
  3. d[i]=INF;//赋值无穷大
  4. d[0]=0;//源点为零
  5. for(i=0;i<n;i++)
  6. {
  7. int x,min=INF;
  8. for(j=0;j<n;j++)
  9. if(!vis[j]&&d[j]<=m)
  10. min=d[x=j];
  11. vis[x]=1;//选中后标记
  12. for(k=0;k<n;k++)
  13. if(d[k]>d[x]+w[x][k])
  14. {
  15. d[k]=d[x]+w[x][k];
  16. father[k]=x;//记录父亲节点,用于回路打印
  17. }
  18. }

回路打印:


  
  1. void find(int x)
  2. {
  3. if(father[x]!=x)
  4. {
  5. find(father[x]);
  6. printf("~~>%d",x);
  7. }
  8. else
  9. printf("%d",x);
  10. }

Dijkstra 算法优化:

          当图中的边很少时用邻接矩阵存就会浪费空间,也就是说当图为稀疏图时可以用邻接表存图。

         首先给每条边编号,然后用first[ u ]保存结点 u 的第一条边的编号,next[ e ]表示编号为 e 的边的“ 下一条边 ”的编号。

代码(有向图):


  
  1. int n,m;//有向图
  2. int first[MAX];//first[]下标为图中点的标号,里面存的是边的序号
  3. int u[MAX],v[MAX],w[MAX],next[MAX];//next[]下标为边的序号,里面存的也是边的序号,
  4. void read()
  5. {
  6. scanf("%d%d",&n,&m);
  7. for(int i=0;i<n;++i)
  8. first[i]=-1;
  9. for(int e=0;e<m;++e)//e为每条边的编号
  10. {
  11. scanf("%d%d%d",&u[e],&v[e],&w[e]);
  12. next[e]=first[u[e]];
  13. first[u[e]]=e;
  14. }
  15. }//先找first[]中存的边,然后依据first[]中存的边作为next[]的下标找到next[]中与之相关的边,一直找到next[]=-1,说明找完了

代码(无向图):


  
  1. int n,m;//无向图
  2. int first[MAX];
  3. int u[MAX],v[MAX],w[MAX],next[MAX];
  4. void read()
  5. {
  6. scanf("%d%d",&n,&m);
  7. for(int i=0;i<n;++i)
  8. first[i]=-1;
  9. for(int e=0;e<m;++e)
  10. {
  11. scanf("%d%d%d",&u[e],&v[e],&w[e]);
  12. next[e]=first[u[e]];
  13. first[u[e]]=e;
  14. i++;
  15. int t;
  16. t=v[i-1];v[i]=u[i-1];u[i]=t;
  17. w[i]=w[i-1];
  18. next[i]=first[u[i]];
  19. first[u[i]]=i;
  20. m++;
  21. }
  22. }



 

文章来源: blog.csdn.net,作者:Linux猿,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/nyist_zxp/article/details/9469369

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。