图文解说 Dijkstra.

Dijkstra

  太多文章了,有些简练,有些一笔带过.自己还是花了些时间才明白,刚脆自己写个图文说明的,希望能让还没明白的,尽快清楚.

  问题:求某点到图中其他所有点的最短路径(权值和最小)

Dijkstra.其实只有4个数据和3句话。明白了这3句话,这个算法就理解了。

第一个数据:还未到达的点的集合。noDone{顶点编号,权值}   顶点编号 和 原点到此编号最小权的候选值

第二个数据:源点 sourceVertex

第三个数据:最新到达的点 lastestVertex

第四个数据:最新到达的点的权  lVCost

第一句话:初始化noDone,把所有除源点之外的点,加入到nodne中。权为这个点直连原点的权,无直线设置为无限大int_max.

第二句话:如果noDone中还有数据,找出noDone中权直最小的点,并把这个点作为 lastestVertex,把它的权作为lVCost,顺便把它从noDone中删除

第三句话:更新noDone中的每个元素的权值,重复第二句话。

分析之前先看流程:

第一句话:初始化noDone,把所有除源点之外的点,加入到nodne中。权为这个点直连原点的权,无直线设置为无限大int_max.

  完成后3个数据

  noDone:(1,3)(2,5)(3,9)(4,max)(5,6)(6,4)

  sourceVertex:0

  lastestVertex:可以设置为sourceVertex的值。

  lVCost:0

第二句话:如果noDone中还有数据,找出noDone中权直最小的点,并把这个点作为 lastestVertex,把它的权作为lVCost,顺便把它从noDone中删除

执行前数据:

  noDone:(1,3)(2,5)(3,9)(4,max)(5,6)(6,4)

  sourceVertex:0

  lastestVertex:0

  lVCost:0

(1,3)这个最小,点为1,权为3。

lastestVertex,更新为1

执行后数据:

  noDone:(2,5)(3,9)(4,max)(5,6)(6,4)

  sourceVertex:0

  lastestVertex:1

  lVCost:3

第三句话:更新noDone中的每个元素的权值,重复第二句话。

执行前数据:

  noDone:(2,5)(3,9)(4,max)(5,6)(6,4)

  sourceVertex:0

  lastestVertex:1

  lVCost:3

  

  如何更新,比较2个值看谁小。第一个值:点到原点的权。第二个值:点到lastestVertex的权+lVCost。

  比如:4点,到原点的权为无限大,到1点的权为8+3(lVCost)=11。11更小。所以(4,max)更新为(4,11)。

  这里其实只需要更新和lastestVertex相连的点,就可以。因为和lastestVertex不相连,那么肯定是原来的直更小,或相等。

执行后数据:

  noDone:(2,5)(3,9)(4,11)(5,6)(6,4)

  sourceVertex:0

  lastestVertex:1

  lVCost:3

分析和思索:

  源点到达某个点可以有很多路径,除非列出所有可能路径,再比较才能得出结果.

  是的,但有一个特例,就是和原点直联的所有点中,权直最小的那个点.暂且叫最近点.

  如图中,权直最小的是3, 1为最近点.

  我们马上就可以确定0->1这条路径,就是0和1的最短路径。

  如何证明:

  反证法:假如有 0->x-->1是最优路径.首先0->x就大于等于 3,因为从0出发,已经确定了0—>1最小。

  式子观察法:最优路径无非就是 x+y+z+...=总权值。x是从原点出发直连的路径。y是点的第二条路...总权值最小。就是去掉y,去掉z,找x最小的。就找到了所有最优路径中的最小的路径。

  想明白这个,才能继续往下处理。所以直连中,权最小的那个,已经确定了最优路径。权值就是直连路径的权。

  看一看,上面的分析已经解释了3句话中的2句了。

  第一句话:初始化noDone,把所有除源点之外的点,加入到nodne中。权为这个点直连原点的权,无直线设置为无限大int_max.

  第二句话:如果noDone中还有数据,找出noDone中权直最小的点,并把这个点作为 lastestVertex,把它的权作为lVCost,顺便把它从noDone中删除

  解释第三句话前先分析:

  如果纯粹继续贪心思路,可以得到另外一种解决方案,这是我在理解 Dijkstra.之前自己想出的思路。        可以看下自己笨拙的思路和别人的对比。

  我们先假设找出了原点到各个点的最短路径。那么第二条最短路径肯定是比第一条长,但比第三条短。废话!

  比第一条长,但比第三条短,在哪里呢?有2个地方,可供候选。

  1)继续从原点出发,找出除掉刚才找到的,第2长的。也就是0-》6。

  2)从新顶点1出发,找出最短的。也就是0-》1-》5。 比较0-》6和0-》1-》5,谁的权直更小。就完成了。

  没有其他可能了吗?为什么?

  首先只要把0->6作为下一个最短路径的候选, 那么0->2,0->3,0->4,0->5,以及由他们产生的路径,就比0-》6长。

  唯一的可能,就是曾经的最优路线0->1,基础上,走下一个点。

  

  思路是这样,没错,但Dijkstra为什么归纳在动态算法中。

  Dijkstra这个时候,并没有直接找下一个最短路径,而选择 更新和lastestVertex相连的点 的权。动态调整 每个点到 原点的 目前所能确定的最小权直。

  以方便他回到第二句话。找到新的最短路径。找到后,继续更新和lastestVertex相连的点 的权,每次都更新,每个点到 原点的 目前所能确定的最小权直。

  步步逼近,步步找出最小的那个。只有最小的才是确定的。最小的那个没有可能再小了,但其他的有可能在这个最小的基础上,饶个弯过来。比原来node中的权直更小。

  哎,这里总感觉说不明白,虽然自己明白。

  写下来把。  任何最短路径的产生,只可能是在原来所有最短路径的基础上,贪心的比较。

  这里要把原点到原点也当成一条最短路径。原点的最短路径就是0->0,

  我们只需要有新的最优顶点,更新和最优顶点相连的点,再来最优顶点。再更新和 这个最优顶点相连的点,上一次的最优顶点的不用管了,因为上次已经更新了。而且没次都会比较,保存最小的。

  所有的noDone中的权直,都是他本身的最小候选值,不是最终最优路径的权直,但是每次最小的那个权直不单是候选值,而且是最终最小权直。

   

  看来还是贴公式更简洁。

代码 c。

struct distance
{
    int noGet;
    int dist;
};

int main()
{
    int matrix[7][7]={
    0,3,5,9,0x7fffffff,6,4,
    3,0,0x7fffffff,0x7fffffff,8,5,0x7fffffff,
    5,0x7fffffff,0,0x7fffffff,2,0x7fffffff,0x7fffffff,
    9,0x7fffffff,0x7fffffff,0,0x7fffffff,0x7fffffff,0x7fffffff,
    0x7fffffff,8,2,0x7fffffff,0,0x7fffffff,0x7fffffff,
    6,5,0x7fffffff,0x7fffffff,0x7fffffff,0,1,
    4,0x7fffffff,0x7fffffff,0x7fffffff,0x7fffffff,1,0
    };

    int minTop=0;
    struct distance noG[6]=
    {
        {1,3},{2,5},{3,9},{4,0x7fffffff},{5,6},{6,4}
    };

    int count_minRd=1;

    int i=0;
    while(count_minRd<7)
    {
        int shortest=0x7fffffff;
        int shortest_i=0;
        for(i=0;i<6;i++)
        {
            if(noG[i].noGet!=-1)
            {
                if(noG[i].dist<=shortest)
                {
                    shortest_i=i;
                    shortest=noG[i].dist;
                }
            }
        }

        minTop=shortest_i;//更新刚找出的最短路径的顶点。

        printf("0->....->%d cost:%d\n",minTop+1,shortest);

        noG[shortest_i].noGet=-1;//简单的赋直为-1,表示删除。

        //动态更新,剩下未处理的点的权值。,对比到源点和到新顶点+新顶点本身权值,取小值。
        for(i=0;i<6;i++)
        {
            if(noG[i].noGet!=-1)
            {
                int i_n=i+1;
                int i_t=minTop+1;
                int newCost=0x7fffffff;//只有相联,才需要更新,因为只有相连的权值才会发生变化。
                if(matrix[0,i_n]<matrix[i_n][i_t]+noG[shortest_i].dist && matrix[i_n][i_t]!=0x7fffffff)
                {
                    newCost=matrix[0,i_n];
                }
                else if(matrix[0][i_n]>matrix[i_n][i_t]+noG[shortest_i].dist && matrix[i_n][i_t]!=0x7fffffff)
                {
                    newCost=matrix[i_n][i_t]+noG[shortest_i].dist;
                }
                if(newCost<noG[i].dist)
                {
                    noG[i].dist=newCost;
                }
            }
        }

        count_minRd++;
    }

    return 0;
}

  

    

时间: 2024-12-20 18:44:34

图文解说 Dijkstra.的相关文章

图文解说:什么是数字签名

图文解说:什么是数字签名 数字签名简介 By David Youd 前言 最近在在网上浏览SSL协议加密有关的文章时,越感对"数字签名"产生了不小的困惑.直接搜索"什么是数字签名",发现了这篇早期文章: http://www.youdzone.com/signature.html,很早,但是依旧耐人寻味.在网贴上也找到了相关的翻译:http://www.ruanyifeng.com/blog/2011/08/what_is_a_digital_signature.h

图文解说:Nginx+tomcat配置集群负载均衡

开发的应用采用F5负载均衡交换机,F5将请求转发给5台hp unix服务器,每台服务器有多个webserver实例,对外提供web服务和socket等接口服务.之初,曾有个小小的疑问为何不采用开源的apache.Nginx软件负载,F5设备动辄几十万,价格昂贵?自己一个比较幼稚的问题,后续明白:F5是操作于IOS网络模型的传输层,Nginx.apache是基于http反向代理方式,位于ISO模型的第七层应用层.直白些就是TCP UDP 和http协议的区别,Nginx不能为基于TCP协议的应用提

Qt编写串口通信程序全程图文解说

(说明:我们的编程环境是windows xp下,在Qt Creator中进行,假设在Linux下或直接用源代码编写,程序稍有不同,请自己修改.) 在Qt中并没有特定的串口控制类,如今大部分人使用的是第三方写的qextserialport类,我们这里也是使用的该类.我们能够去 http://sourceforge.net/projects/qextserialport/files/ 进行下载,也能够去下载我上传到网上的: http://download.csdn.net/source/176278

UIViewContentMode 图文解说

在iOS应用开发中我们常常要对视图的contentMode属性进行设置,尤其在使用UIImageView视图时设置这个属性的概率很高.我们知道contentMode的类型是UIViewContentMode的枚举,那么其每个值是什么含义,设置后会有什么效果呢?下面就来总结下. UIViewContentModeLeft 如果将UIImageView对象的contentMode设置为UIViewContentModeLeft,其内部的图片会按照原有的尺寸大小,以垂直居中,水平居左的方式显示.见UI

64位win7下安装SQL Server 2008(图文解说版)

运行sql安装 单击安装-全新的sql server独立安装,如果我们准备好了故障转移群集,那么我们就可以创建故障转移群集sql 常规检查 一笑而过 选择版本,或者输入密钥自动识别版本 授权协议 支持文件安装 安装完成开始检查自身 俩警告,一个是.net警告,说没网络会延迟,或者需要下载文件 一个数要打开端口,无视了,晚点再打开 选择安装的功能,sql数据库和管理工具 选择实例 驱动器检查 选择服务账户,如图选择的是本地系统账户 验证模式:sql和本地模式两种,输入密码,另外添加管理员,可以添加

使用openfire,spark,fastpath webchat搭建在线咨询服务详细图文解说

这几天试用了下openfire相关应用,搭建一个简单的在线咨询服务,有点类似阿里旺旺,可以web页面在线咨询,也可以加为好友在pc客户端中咨询 使用场景:企业业务咨询 1.在官网http://www.igniterealtime.org/index.jsp,下载openfire,spark 2.安装spark.exe,解压openfire.zip 3.执行\openfire_3_9_3\openfire\bin\下的openfire.exe,点击launch admin进入管理员配置界面 4.配

图文解说视频直播原理-zz

本文主要介绍rtmp&hls视频直播原理,文章最早发表在我们的微信公众号上,详见这里,欢迎关注微信公众号blackerteam,更多详见www.blackerteam.com 现在视频直播很火,应用场景很多,比如在线教育.美女秀场.在线医疗.电商活动.游戏直播.体育直播,中国好声音. 市面上与之相关的app也很多,比如搜狐视频.乐视体育.虎牙直播.9158,作为it人员我们可能更关心其背后的实现原理, 所以下面我们通过6张图来进行介绍: 图一:直播流程,以在线教育为例 说明:GotyeLive是

plsql无法连接64位oracle数据库的解决方法(图文解说)

oracle11g下载页面:http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html,找到适合自己系统的数据库,需要将file1和file2都下载下来,压缩到同一个文件夹下才能进行安装,否则安装不了. 接着用免安装的plsql连接数据库试了试,发现没有连接的权限可选,如图 直接输入用户名.密码和数据库名,提示如下: 说明plsql是不可以直接连接64位oracle数据库,只能连接32位.既

七牛用户搭建c# sdk的图文解说

Qiniu 七牛问题解答 问题描述:很多客户属于小白类型.但是请不要随便喷七牛的文档站.因为需要一点http的专业知识才能了解七牛的api文档.现在我给大家弄个c# sdk的搭建步骤 问题解决方案 1,首先要在vs中安装nuget NuGet的安装(我的开发环境是Visual Studio 2013 旗舰版,故以此为例): 主菜单->工具->扩展和更新,打开如下界面,点击左侧的"联机"搜索nuget,然后搜索到安装. 2,应用nuget来安装qiniu sdk 你可以右键你