深入解析最短路径算法

2023-05-16

转载自: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*搜索算法

第六节 结束语
      想想,写写,画画......
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入解析最短路径算法 的相关文章

  • 第四章 智能指针

    裸指针问题如下 xff1a 裸指针在声明中并未指出 xff0c 裸指针指涉到的是单个对象还是一个数组 裸指针在声明中也没有提示是不是要对其进行虚构 换言之 xff0c 无法得知指针是否拥有其指涉的对象 或者是否空悬指针的析构是不是拥有重载的
  • dpdk无锁队列

    这篇博客是从网上博客整理摘抄而来 xff0c 具体参考的博客内容在文末给出 Linux无锁队列 kfifo概述 Linux内核中有一个先进先出的数据结构 xff0c 采用环形队列的数据结构来实现 xff0c 提供一个无边界的字节流服务 最重
  • C++虚函数和虚函数表原理

    虚函数的地址存放于虚函数表之中 运行期多态就是通过虚函数和虚函数表实现的 类的对象内部会有指向类内部的虚表地址的指针 通过这个指针调用虚函数 虚函数的调用会被编译器转换为对虚函数表的访问 xff1a ptr gt span class hl
  • 非递归快排

    非递归快排 通过使用栈来模拟函数栈的调用 xff0c 每次将首尾指针存入到栈中 xff0c 并对首尾之间区域进行快排 span class hljs preprocessor include lt iostream gt span span
  • ppt基础篇--自学笔记

    字体 给文字加边框 加背景 底纹logo 方框 加透明框 拆分 字体镂空 不规则图形 xff08 结合背景 xff09 图片 删除背景 xff08 两张叠加 xff09 点击设置透明色 xff08 背景为纯色 xff09 背景虚化 添加矩形
  • Golang Assertion

    Go中所有的类型都可以被转化成interface xff0c 通常在传入可变参数中的API中 xff0c 可变参数的类型就是interface func typeConversion strs interface ret string fo
  • 解决Idea Maven生成的jar运行出现“没有主清单属性”问题

    1 问题描述 通过maven构建了jar文件 xff0c 如图所示 2 命令窗口运行jar 提示 没有主清单属性 2 1 分析问题 在打包构建的jar目录内 xff0c 可以看到有一个MANIFEST MF文件 xff0c 如图所示 xff
  • VMWare虚拟机扩展磁盘空间(扩充root根目录空间)

    1 扩展虚拟机磁盘空间 Vm虚拟机下Linux扩展原有磁盘空间 xff0c 10G 10G的基础上不能满足需求 xff0c 只好进行磁盘扩展 调整到合适的磁盘空间 需注意以下几点 xff1a linux只能扩展磁盘容量而不能减小 xff0c
  • vim批量操作技巧

    vim批量操作技巧 目录 vim批量操作技巧一 列操作二 批量复制与删除三 批量替换四 批量注释 一 列操作 删除列 在正常模式下 xff08 一般按Esc键就是 xff09 光标定位 CTRL 43 v 进入 VISUAL BLOCK 可
  • VMware17pro图解安装 Rocky Linux 9.1

    1 引言 Rocky Linux为CentOS Linux 的继承者 RHEL 9 的复制品 下面是在VMware上安装实例 1 1 下载安装VMware VMware下载 xff1a VMware官网下载 1 2 下载Rocky9 x镜像
  • (二)Proxmox7.3 VE 安装Rocky9.1系统

    1 准备环境 PVE虚拟管理平台能正常访问 https IP 8006 由于我的服务器磁盘空间不足4G了 xff0c 这里我就安装个debian虚拟机来演示吧 xff0c 毕竟它小巧不占用地方 xff0c 主要是想记录好pve创建虚拟机的步
  • No Spring Session store is configured: set the 'spring.session.store-type'

    发现session store type使用来存放session的存储方式 xff0c 目前Spring boot中只支持Redis方式 由于本应用暂无需将session放入redis的需求 xff0c 故这里就可以将session sto
  • idea修改git账号及密码的方法

    IDEA修改git账号及密码的方法 xff1a 1 file gt settings gt passwords 这里写图片描述 默认In KeePass 保存密码 切换到Do not save forget password after r
  • KETTLE使用教程

    1 Kettle的下载与安装 kettle的最新下载地址 xff1a http community pentaho com projects data integration 由于Kettle 是采用java 编写 xff0c 因此需要在本
  • Hive lag()与lead() 函数

    lag与lead函数是跟偏移量相关的两个分析函数 xff0c 通过这两个函数可以在一次查询中取出同一字段的前N行的数据 lag 和后N行的数据 lead 作为独立的列 从而更方便地进行进行数据过滤 这种操作可以代替表的自联接 xff0c 并
  • WebService简单案例实例

    本周工作日即将结束 xff0c 下周项目经理安排了一项任务可能需要使用到webservice xff0c 但本人之前尚未使用过 xff0c 网上查了一些案例看了看 在此小记一篇留作日后回首也希望可以帮助到查看者朋友 1 什么是WebServ
  • Java中CountDownLatch介绍与应用

    正如每个Java文档所描述的那样 xff0c CountDownLatch是一个同步工具类 xff0c 它允许一个或多个线程一直等待 xff0c 直到其他线程的操作执行完后再执行 在Java并发中 xff0c countdownlatch的
  • Windows下搭建 Rust 开发环境

    Rust 支持很多的集成开发环境 xff08 IDE xff09 或开发专用的文本编辑器 查看官网公布支持的开发工具 Rust 的编译工具依赖 C 语言的编译工具 xff0c 可以使用 Microsoft C 43 43 生成工具 或者 M
  • ubuntu安装mysql错误处理

    1 错误信息 W GPG error http repo mysql com apt ubuntu xenial InRelease The following signatures were invalid KEYEXPIRED 1487

随机推荐

  • 如何安装 SUSE Linux Enterprise Server 15 SP4

    SUSE Enterprise Linux Server SLES 是一种现代的模块化 Linux 发行版 xff0c 主要为服务器和大型机开发 它专注于支持生产工作负载 xff0c 通常由大型组织用于托管和运行应用程序 SUSE还支持传统
  • Xcode 之nib文件

    在iOS 开发中 xff0c 不可避免的肯定会接触到interface builder xff0c 也就是IB窗口 这儿IB就是使用nib文件储存GUI资源 这儿所说的nib文件是一种数据文件 xff0c 用于存储可在应用程序需要时使用的一
  • 出现 mkdir() Permission denied 问题解决

    正常我们在写项目的时候 xff0c 本地可以可以使用 xff0c 部署到服务器为什么就出现这个错误了呢 xff1f 因为我们服务器使用的是Linux系统 xff0c 默认的目录权限没有全部开启的 xff0c 造成执行创建文件的时候报错 xf
  • 报错A non well formed numeric value encountered(Thinkphp5时间戳自动转换问题)

    数据库表字段设置 datetime类型 xff0c 渲染的时候系统会自动进行转换 xff0c datetime类型再做一次转换就出现了 A non well formed numeric value encountered 错误 解决方法
  • 【开箱即用】VirtualBox Ubuntu20.04.6、22.04.2虚拟机下载

    简介 今天继续我们的开箱即用系列 为了简化Ubuntu虚拟机的制作 xff0c 减少重复劳动 xff0c 提高生产效率 xff0c 本公众号提供了基于VirtualBox制作的Ubuntu纯净虚拟机 xff0c 供学习交流使用 下载 Ubu
  • anaconda安装后桌面无快捷方式

    在安装目录的Anaconda3 Scripts中找到需要的exe文件 xff0c 生成快捷方式到桌面即可 如果想要改变快捷方式的图标 xff0c 可以在桌面快捷方式上右键选择属性 xff0c 点击更改图标 浏览 输入图标地址 在安装的Ana
  • 洛谷 [P1825 [USACO11OPEN]Corn Maze S] {搜索|BFS} 奋斗的珂珂~

    题目描述 This past fall Farmer John took the cows to visit a corn maze But this wasn t just any corn maze it featured severa
  • 个人对测试的理解--自动化UI测试

    系列文章目录 整理下个人对测试的一些想法和理解 xff0c 个人之见 文章目录 系列文章目录整体思路UI测试WEB UIselenium快速入门 APP UIappnium快速入门 airtest快速入门 桌面应用 UIpywinauto快
  • 什么是对象?什么是面向对象程序设计?面向对象语言有什么优点?

    在初学面向对象语言的时候 xff0c 很多书都会有这样的句子 一切都是对象 那么对象究竟是什么呢 xff1f 是不是一切的事物都叫对象 xff1f 但这里的对象并不是我们日常生活中的对象 xff08 事物 xff09 xff0c C 中我们
  • 远程桌面无法复制东西

    今天突然用远程桌面复制的时候发现无法复制东西 xff0c 然后上网查了一下 xff0c 解决办法就是重启一下他 xff1a rdpclip exe 重启方法就是打开任务管理器 xff0c 杀掉rdpclip exe xff0c 然后再运行他
  • ubuntu 20.0.4 qt 程序打包发布及解决 xcb 加载错误的解决方法

    ubuntu 中如何通过 批处理命令进行 qt 程序的打包发布 xff0c 参见 博文 xff1a https blog csdn net qq21497936 article details 85396652 ops request mi
  • mamp pro apache 中文目录浏览乱码

    解决办法 xff1a 打开mamp pro apache配置文件httpd conf xff0c 在任意一行后加入 xff1a span class hljs attribute IndexOptions Charset span 61 s
  • PyTorch入门二:LSTM实现MNIST手写数字识别

    参考博客 xff1a https blog csdn net winycg article details 88937583 LSTM Long Short Term Memory xff0c 长短时记忆网络 xff0c 主要用于传统RNN
  • Python之Networkx详解

    文章目录 1 安装Networkx2 Networkx的基本使用2 1 导入networkx2 2 创建Graph2 3 给Graph添加边2 3 Graph基本信息获取2 4 Graph的绘制2 5 Graph的其他内置算法 3 其他3
  • 基于gunicorn部署flask项目

    文章目录 1 WSGI协议2 gunicorn介绍3 gunicorn安装4 gunicorn使用4 1 基于Flask创建python服务4 2 配置参数 启动应用服务4 2 1 命令行配置gunicorn参数4 2 2 文件配置guni
  • Python日志记录库——loguru

    loguru简单且强大的日志记录库 https zhuanlan zhihu com p 446232870
  • 批量删除word中的换行符号

    在Word中 xff0c 回车符有两种 xff0c 即 硬回车 和 软回车 硬回车是直接敲键盘上的Enter键 xff0c 软回车是按键盘上的 Shift 43 Enter 硬回车 输入快捷键 xff1a Enter xff0c 作用 xf
  • 把字符串中的字符进行排序

    把字符串中的字符进行排序 xff1a 把字符串中的字符进行排序 toCharArray xff1a 把字符串转换为字符数组 valueOf xff1a 把字符数组转换为字符串 1 把字符串中的字符进行排序 举例 xff1a 34 dacge
  • 【Ubuntu切换内核版本】NVIDIA-SMI has failed because it couldn‘t communicate with the NVIDIA driver.

    文章目录 一 有图形界面二 无图形界面2 1 查看当前内核版本2 2 查看内核启动顺序2 3 切换内核 服务器信息 xff1a Ubuntu 18 04 服务器重新启动后 xff0c 内核可能被自动更新 xff0c 这就会造成开机后服务器有
  • 深入解析最短路径算法

    转载自 xff1a http blog csdn net fengchaokobe article details 7478774 第一节 问题的提出及解决方法 所谓最短路径问题 xff0c 可以说有两种情况来描述 描述一 xff1a 在图