深入解析最短路径算法

深入解析最短路径算法转载自:http://blog.csdn.net/fengchaokobe/article/details/7478774  第一节问题的提出及解决方法      所谓最短路径问题,可以说有两种情况来描述。      描述一:在图论中,指的是寻找图中两个节点之间的最短距离。如下图      描述二:在现实生活中,指的是找到从一个地方到另一个地方的最近距离。如下图

大家好,又见面了,我是你们的朋友全栈君。

转载自:http://blog.csdn.net/fengchaokobe/article/details/7478774
  

第一节 问题的提出及解决方法
       所谓最短路径问题,可以说有两种情况来描述。
       描述一:在图论中,指的是寻找图中两个节点之间的最短距离。如下图

深入解析最短路径算法

       描述二:在现实生活中,指的是找到从一个地方到另一个地方的最近距离。如下图

深入解析最短路径算法

       上述两种情况的本质是一样的,即求一个点到另一个点的最短路径。好了,问题已经提出来了,那怎么解决呢?解决该问题的方法还是比较多的,不过由于各个路径算法所对应的问题条件不同,我们可根据不同的情况,选择不同的路径算法。
       本文将介绍三种最短路径算法,分别是:戴克斯特拉算法(Dijkstra algorithm),弗洛伊德算法(Floyd algorithm)以及A*搜索算法。


第二节 戴克斯特拉算法(Dijkstra algorithm)


       该算法解决的是有向图中单个源点到其他顶点的最短路径问题。


戴克斯特拉算法的实现过程如下:


       第一步:用带权的矩阵WeiArcs来表示带权有向图,如果图中的两个顶点vi和vj是连通的,则用WeiArcs[i][j]表示这两个顶点所形成边的权值;如果vi和vj不连通,即<vi,vj>这条边不存在,那么将WeiArcs[i][j]置为∞。
       第二步:设S为已求得的从某一顶点v始发的最短路径的终点的集合,且S的初始状态为空,初始化时,将始发顶点置于S集合中。那么从v出发到图中其余各个顶点vi可能达到的最短路径长度的初值为D[i]。
       第三步:选择一顶点vj,使得vj就是当前求得的一条从顶点v出发的最短路径的终点。此时令S = S ∪ {vj}。
       第四步:修改从v出发到集合V-S(V为图顶点的集合)中任一顶点vk可达的最短路径长度。如果D[j]+WeiArcs[j][k] < D[K],则D[k] = D[j] + WeiArcs[j][k]。
       第五步:重复操作第三步、第四步共N-1次,由此就能求得从v出发到图中其余各个顶点的最短路径。

       好了,实现过程就是这样。不过光有文字描述不行,要更直白的表达这个过程,我认为用图像表述是一个很好的选择。如下图所示

深入解析最短路径算法

深入解析最短路径算法

深入解析最短路径算法

从运算过程表中,我们可知v0到其余个点的最短路径,如下图

深入解析最短路径算法

上述过程描述的戴克斯特拉算法的代码如下:

int ShortPath(MGraph G,int v0,PathMatrix &P,ShortPathTable &D)  
{  
    //用戴克斯特拉算法求有向图G中v0顶点到其余顶点v的最短路径P[v]及带权长度D[v]。  
    //若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。  
    //final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径。  
      
    for(v = 0;v < G.vexmun;v++)  
    {  
        final[v] = FALSE;  
        D[v] = G.WeiArcs[v0][v];  
        for(w = 0;w < G.vexnum;w++)  
            P[v][w] = FALSE;    //设空路径  
        if(D[v] < INFINITY)  
        {  
            p[v][v0] = TRUE;  
            p[v][v] = TRUE;  
        }  
    }  
      
    D[v0] = 0;final[v0] = TRUE; //初始化,v0顶点属于S集合  
      
    //开始主循环,每次求得v0到某个顶点v的最短路径,并将v加到S集合中  
    for(i = 1; i < G.vexnum; i++)    //其余G.vexnum - 1个顶点  
    {  
        min = INFINITY; //当前所知离v0点的最近距离  
        for(w = 0;w < G.vexnum; i++)  
        {  
            if(!final[w])   //w顶点在V - S中  
            {  
                if(D[w] < min)   //w顶点离v0更近  
                {  
                    v = w;  
                    min = D[w];  
                }  
            }  
        }  
        final[v] = TRUE;    //离v0顶点最近的v加入到S中  
          
        for(w = 0;w < G.vexnum;w++)  //更新当前最算路径及距离  
        {  
            if(!final[w] && (min + G.WeiArcs < D[w]))  
            {  
                D[w] = min + G.WeiArcs[v][w];  
                //p[w] = P[v] + P[w];  
                P[w] = P[v];  
                P[w][w] = TRUE;  
            }  
        }  
    }  
    return 0;  
}  

ok,Dijkstra algorithm介绍完了。

第三节 弗洛伊德算法(Floyd algorithm)


       该算法解决的是有向带权图中两顶点之间最短路径的问题。

弗洛伊德算法的设计过程如下:


       用带权的矩阵WeiArcs来表示带权有向图,如果图中的两个顶点vi和vj是连通的,则用WeiArcs[i][j]表示这两个顶点所形成边的权值;如果vi和vj不连通,即<vi,vj>这条边不存在,那么将WeiArcs[i][j]置为∞。
       要求:求节点vi到节点vj的最短路径。
       设D(i,j,k)为从节点vi到节点vj的以vk(vk∈(0,1,…k))节点为中间节点的最短路径的长度。例如:从vi到vj这条路径上经过节点vm和节点vk,那么可表示为:vi–>vm–>vk–>vj。

那么,就有:1.若最短路径经过节点vk,则D(i,j,k) = D(i,k,k-1) + D(k,j,k-1);
                      2.若最短路径不经过节点vk,则D(i,j,k) = D(i,j,k-1)。


所以,求的vi到vj的最短路径可表示为:

D(i,j,k) = min(D(i,k,k-1) + D(k,j,k-1), D(i,j,k-1))。

老办法,图示的过程如下:

深入解析最短路径算法

求解的过程见下图:

深入解析最短路径算法


深入解析最短路径算法

上述过程描述的弗洛伊德算法的代码如下:

int ShortPath(MGraph G,int v0,PathMatrix &P,ShortPathTable &D)  
{  
    //用Floyd算法求有向图中各对顶点v和w之间的最短路径P[v][w]及其带权长度D[v][w]。  
    //若p[v][w][u]为TRUE,则u是从v到w当前求得的最短路径上的顶点  
    for(v = 0;v < G.vexnum;v++)  
        for(w = 0;w < G.vexnum;w++)  
        {  
            D[v][w] = G.arcs[v][w];  
            if(D[v][w] < INFINITY)   //从v到w有直接路径  
            {  
                P[v][w][u] = TRUE;  
                P[v][w][w] = TRUE;  
            }  
        }  
          
    for(u = 0;u < G.vexnum;u++)  
        for(v = 0;v < G.vexnum;v++)  
            for(w = 0;w < G.vexnum;w++)  
            {  
                if(D[v][u] + D[u][w] < D[v][w])  //从v经u到w的一条更短路径  
                    D[v][w] = D[v][u] < D[u][w];  
                for(i = 0;i < G.vexnum;i++)  
                    P[v][w][i] = P[v][u][i] || P[u][w][i];  
            }  
    return 0;  
}  

第四节 A*搜索算法


       A*搜索算法,俗称A星算法。这是一种在图平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中的NPC的移动计算,或线上游戏的BOT的移动计算上。该算法像Dijkstra算法一样,可以找到一条最短路径;也像BFS一样,进行启发式的搜索。

       A*算法最核心的部分,就在于它的一个估值函数的设计上:f(n)=g(n)+h(n)。其中,g(n)表示从起始点到任一点n的实际距离,h(n)表示任意顶点n到目标顶点的估算距离,f(n)是每个可能试探点的估值。这个估值函数遵循以下特性:


       •如果h(n)为0,只需求出g(n),即求出起点到任意顶点n的最短路径,则转化为单源最短路径问题,即Dijkstra算法;
       •如果h(n)<=“n到目标的实际距离”,则一定可以求出最优解。而且h(n)越小,需要计算的节点越多,算法效率越低。

       我们可以这样来描述:从出发点(StartPoint,缩写成sp)到终点(EndPoint,缩写成ep)的最短距离是一定的,于是我们可以写一个估值函数来估计出发点到终点的最短距离。如果程序尝试着从出发点沿着某条线路移动到了路径上的另一个点(Otherpoint,缩写成op),那么我们认为这个方案所得到的从sp到ep间的估计距离为:从sp到op实际已走的距离加上估计函数估出的从op到ep的距离。如此,无论我们的程序搜索展开到哪一步,都会得到一个估计值,每一次决策后,将评估值和等待处理的方案一起排序,然后挑出待处理的各个方案中最有可能是最短路线的一部分的方案展开到下一步, 一直循环直到对象移动到目的地,或所有方案都尝试过,却没有找到一条通向目的地的路径则结束。



A*搜索算法的图解过程请看:http://blog.vckbase.com/panic/archive/2005/03/20/3778.html

第五节 相关说明


参考资料:数据结构(严蔚敏)、维基百科之A*搜索算法

第六节 结束语


      想想,写写,画画……

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/136185.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 大型网站的核心架构要素

    大型网站的核心架构要素

  • Android 4.0开发之GridLayOut布局实践

    Android 4.0开发之GridLayOut布局实践在上一篇教程中http://blog.csdn.net/dawanganban/article/details/9952379,我们初步学习了解了GridLayout的布局基本知识,通过学习知道,GridLayout可以用来做一个象TableLayout这样的布局样式,但其性能及功能都要比tablelayout要好,比如GridLayout的布局中的单元格可以跨越多行,而tablelayout则不

  • 安装sklearn库的命令_sklearn库手册中文版pdf

    安装sklearn库的命令_sklearn库手册中文版pdf首先,SKlearn需要三个依赖库,分别进行安装。如果已经安装好了Python,那么可以直接运用pip命令来安装这些库。pip命令自带版本一般比较旧,需要更新。使用如下命令更新:更新完成后,直接运行:pipinstallnumpypipinstallmatplotlibpipinstallscipypipinstallsklearn注:直接利用ana…

    2022年10月17日
  • pycharm在linux系统汉化,PyCharm中文乱码问题的解决

    pycharm在linux系统汉化,PyCharm中文乱码问题的解决这几天一直挺困扰的是使用PyCharm之后一直对中文的乱码,即使添加了很多别人说的类似于#coding:utf-8的语句但是还是报错,让我抓狂,但是今天终于找到了解决的办法,还真的是让人很高兴啊,哈哈哈这是报错的窗口:典型的无法识别中文,在头添加#coding:utf-8之后还是报错的状态,所以就用了下面的方法,首先,我用的是PyCharm的4.5.3最新的版本进入设置界面,找到Editor–…

  • Jenkins详细安装与构建部署使用教程[通俗易懂]

    Jenkins详细安装与构建部署使用教程[通俗易懂]     Jenkins是一个开源软件项目,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能。Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作,功能包括:1、持续的软件版本发布/测试项目。2、监控外部调用执行的工作。本文使用的Linux:Ubuntu其中JDK、Tomcat、SVN服务器请看这里Ubuntu安装配置JDK、Tomcat、SVN…

  • python基础知识(一) 计算机概念,python的初步认识[通俗易懂]

    python基础知识(一) 计算机概念,python的初步认识[通俗易懂]Python基础知识计算基础知识1.cpu人类的大脑运算和处理问题2.内存临时存储数据断电就消失了3.硬盘永久存储数据4.操作系统调度硬件设备之间数据交互python的应用和历

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号