数据结构与算法之图(中)

最短路径问题

现实生活中经常会碰到下面这些这样的问题:
从家去博物馆走那条路最近、从北京到广州怎么走高速费最少等等
毕竟精打细算才是正道嘛 屁!就是穷
这其实就是我们图里的最短路径问题,也可以说是最优路径问题(哪怕远一点,高速费便宜就行嘻嘻)。我们把路径起始的第一个顶点称为源点,最后一个顶点称为终点。所谓单源最短路径问题,就是从某一顶点v0 出发,找从它到图中其他各个顶点的最短路径。
在这里插入图片描述
最短路径问题依据图的类别不同有不同的解决办法
在这里插入图片描述
其实无权图的最短路径问题,或者所有权值一样的有权图最短路径问题,在解决方法上都可以用BFS稍微改动来实现,之前讲BFS时就说过他是一圈一圈往外找的找到了肯定就是最短的,可能往外了还会有符合条件的,BFS类似于树当中的层序遍历,我们知道层序遍历第一个找到的叶节点一定是离根节点最近的。
在这里插入图片描述
在这里插入图片描述

迪杰斯特拉算法

求解单源最短路径问题的算法
在这里插入图片描述

迪杰特斯拉算法其实是一种贪心的思想每一步都是按递增顺序找到的最短路。
比如他想找到从 i 到 j 的最短路,他就会把与 j 有关的顶点k遍历一遍,把从i到k的总权值加上从k到 j 的权值最小的当做从i 到 j 的最短路径,那你可能就要问了i到k的总权值哪来的,那不一样的嘛,又从i到k执行一遍刚刚的这一波操作不就好了。
康康代码:

void Dijkstra(int src)
{
    int i;
    for(i=0;i<n;i++)
    {
        //开始时先把每两条边之间的权值当作他们之间的最短距离
        dis[i]=map[src][i];//dis数组存的就是从起点到各个点的最短路径
        vis[i]=0;//标记数组初始化为未访问过
    }
    dis[src]=0;//起点到起点最短路径为0
    vis[src]=1;
    int j,k,tmp;
    for(i=0;i<n;i++)//要把所有的顶点都遍历一遍
    {
        tmp=INF;//INF为不可能的值
        for(j=0;j<n;j++)
            if(!vis[j] && tmp>dis[j])//找到没访问过的且距起点src最短的点
            {
                k=j;
                tmp=dis[j];//记录下没比之改的最短距离
            }
        if(tmp==INF)//没变就没必要再继续下去了
            break;
        vis[k]=1;
        for(j=0;j<n;j++)//找边他周围的点
            if(!vis[j] && dis[j]>dis[k]+map[k][j])//如果出现了上面我们说的那种情况
                dis[j]=dis[k]+map[k][j];//更新最短距离
    }
}

弗洛伊德算法

求解多元最短路径的办法
有些人可能会说多元最短路直接遍历调用迪杰特斯拉算法不就行了吗,我们来比较一下
在这里插入图片描述
看到他的时间复杂度是不是很想直到这个Floyd算法是怎么实现的呢
其实他的思想就是逐个顶点试探法
步骤:
1.初始时设置一个n阶方阵,令其对角线元素为0,若存在弧<Vi,Vj>,则对应元素为权值;否则为µ。
2.逐步试着在原直接路径中增加中间顶点,若加入中间点后路径变短,则修改之;否则,维持原值。
3.所有顶点试探完毕,算法结束。
在这里插入图片描述

发布了32 篇原创文章 · 获赞 5 · 访问量 893

猜你喜欢

转载自blog.csdn.net/LebronGod/article/details/104466864