学习笔记: 图的最短路径

图的最短路径

带权图的最短路径

从某顶点(源点)出发到另一顶点(目的点)的路径中,有一条各边(或弧)权值之和最小的路径称为最短路径。

  1. 从单源点到其余各点的最短路径 迪杰斯特拉算法(Dijkstra)
  2. 每一对顶点之间的最短路径 弗洛伊德算法 (Floyd)

迪杰斯特拉(Dijkstra)算法

迪杰斯特拉(Dijkstra)算法:

依最短路径的长度递增的次序求得各条路径。

其中,从源点v0到顶点vi的最短路径是v0到各点路径集合长度中长度最短者。

路径长度最短的最短路径的特点:

在这条路径上,必定只含有一条弧,并且这条弧的权值最小。(设为v0->vk)

下一条路径长度次短的最短路径特点:

它只可能有两种情况:或者是直接从源点到该点vi(只含一条弧);或者是从源点经过顶点vk,再到达vi(由两条弧组成)。

再下一条路径长度次短的最短路径特点:

它可能有两种情况:或者是直接从源点到该点(只含一条弧);或者是从源点经过顶点vk,vi再到达该顶点(由多条弧组成)

其余最短路径:

它或者是直接从源点到该点(只含一条弧);或者是从源点经过已求得最短路径的顶点,再到达该顶点

在这里插入图片描述

迪杰斯特拉(Dijkstra)算法的基本思想:

  1. 初始时,集合S中仅包含源点v0,集合V-S中包含除源点v0以外的所有顶点。v0到V-S中各顶点的路径长度或者为某个权值(如果它们之间有弧相连),或者为无穷(没有弧相连)。
  2. 按照最短路径长度递增的次序,从集合V-S中选出到顶点V0路径长度最短的顶点vk加入到S集合中。
  3. 加入vk之后,为了寻找下一个最短路径,必须修改从v0到集合V-S中剩余所有顶点vi的最短路径。若在最短路径上加入vk之后,使得v0到vi的路径长度比原来没有加入vk时的路径长度短,则修正v0到vi的路径长度为其中较短的。
  4. 重复以上步骤,直至集合V-S中的顶点全部被加入到集合S中为止。

存储结构

  1. 带权邻接矩阵用g.arcs[ ] [ ]表示:

    用g.arcs[i] [j].adj表示弧<vi,vj>上的权。

  2. 将顶点分为两组:S,V-S

    S中存放已求得最短路径的终点的集合。

  3. 借助辅助一维数组dist[ ]

    若vi属于S,dist[i]表示源点到vi的最短路径长度

    若vi属于V-S,dist[i]表示源点到vi的只包括S中的顶点为中间顶点的最短路径。

    初始:S={v0},v0为源点

    ​ dist[i]=g.arcs[0] [i].adj; (vi属于V-S)

  4. 二维数组path[] [ ]记录某顶点是否加入到集合S中

    如果path[i] [0] = 1,

    则表示顶点vi加入到集合S中,并且path[i]所在的行最终记录了源点到vi的最短路径上的各个顶点。

    否则,path[i] [0]=0,则表示顶点vi还在集合V-S中。
    在这里插入图片描述

代码实现:

void Dijkstra(AdjMatrix *G,int start,int end,int dist[],int path[][MAXVEX]){
    int mindust,i,j,k,t=1;
    for(i=1;i<=G->vexnum;i++){
        dist[i]=G->arcs[start][i];
        if(G->arcs[start][i]!=INFINITY)
            path[i][1]=start;
    }
    path[start][0]=1;
    for(i=2;i<=G->vexnum;i++){
        mondist=INFINITY;
        //选择最小权值的路径
        for(j=1;j<=G->vexnum;j++)
            if(!path[j][0]&&dist[j]<mindist)
            {
                k = j;
                mindist = dist[j];
            }
        	if(mindist==INFINITY) return;
        	path[k][0]=1;
        for(j=1;j<=G->vexnum;j++)
        {
            if(!path[j][0]&&G->arcs[k][j]<INFINITY&&dist[k]+G->arcs[k][j]<dist[j])
            {
                dist[j]=dist[k]+G->arcs[k][j];
                t=1;
                while(path[k][t]!=0)
                {
                    path[j][t]=path[k][t];
                    t++;
                }
                path[j][i] = k;
                path[j][t+1] = 0;
            }
        }
    }
}

在这里插入图片描述
开心完结撒花!!!!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿小张的日常笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值