图的搜索(二):贝尔曼-福特算法、狄克斯特拉算法和A*算法

图的搜索(二):贝尔曼-福特算法、狄克斯特拉算法和A*算法

贝尔曼-福特算法

贝尔曼-福特(Bellman-Ford)算法是一种在图中求解最短路径问题的算法。最短路径问题就是在加权图指定了起点和终点的前提下,寻找从起点到终点的路径中权重总和最小的那条路径。

在这里插入图片描述

设置A为起点,G为终点。

在这里插入图片描述

首先设置各个顶点的初始权重 :起点为 0,其他顶点为无穷大(∞)。这个权重表示的是从 A 到该顶点的最短路径的暂定距离。随着计算往下进行,这个值会变得越来越小,最终收敛到正确的数值。

在这里插入图片描述

选中候补顶点,分别计算这条边从一端到另一端的权重,计算方法为:“顶点原本的权重+边的权重”

在这里插入图片描述

计算权重,如果计算结果小于顶点的值,就更新这个值。

如图,计算A到B的权重:顶点 B 的权重是无穷大,比 9 大,所以把它更新为 9。更新时需要记录计算的是从哪个顶点到该顶点的路径。

再次计算B到A的权重:B 的权重为 9,从 B 到 A 的权重便为 9+9=18。与顶点 A 现在的值 0 进行比较,因为现在的值更小,所以不更新。

A到C的路径计算同理。接下来计算B到C的路径。

在这里插入图片描述

在进行B-C计算时,发现A-C-B的路径比A-B的路径更短,于是更新如下:

在这里插入图片描述

接着对所有的边进行更新操作

在这里插入图片描述

更新完所有的边后,第 1 轮更新就结束了。接着,重复对所有边的更新操作,直到权重不能被更新为止。

在这里插入图片描述

第二轮更新后,顶点 B 的权重从 8 变成了 7,顶点 E 的权重从 9 变成了 8。接着进行第三轮更新。发现第三轮更新后,所有顶点的权重不再更新,操作结束。算法的搜索流程也就此结束,我们找到了从起点到其余各个顶点的最短路径。

在这里插入图片描述

根据搜索结果可知,从起点 A 到终点 G 的最短路径是 A-C-D-F-G,权重为 14。

将图的顶点数设为 n、边数设为 m。该算法经过 n 轮更新操作后就会停止,而在每轮更新操作中都需要对各个边进行 1 次确认,因此 1 轮更新所花费的时间就是 O(m),整体的时间复杂度就是 O(nm)。

有向图与以上步骤相同,只需按照边所指向的方向来计算即可。

计算最短路径时,边的权重代表的通常都是时间、距离或者路费等,因此基本都是非负数。不过,即便权重为负,贝尔曼 - 福特算法也可以正常运行。

如果闭环中有负数权重,就不存在最短路径。

狄克斯特拉算法

狄克斯特拉( Dijkstra)算法也是求解最短路径问题的算法,使用它可以求得从起点到终点的路径中权重总和最小的那条路径。

在这里插入图片描述

仍然设A为起点,G为终点。

在这里插入图片描述

与贝尔曼-福特算法相同,将起点设置为0,其他顶点设置为无穷大。设置从A出发,寻找可以从目前所在的顶点直达且尚未被搜索过的顶点,此处为顶点 B 和顶点 C,将它们设为下一步的候补顶点。

在这里插入图片描述

计算后结果如上图。计算方法是“目前所在顶点的权重+目前所在顶点到候补顶点的权重”。与贝尔曼-福特算法类似。

在这里插入图片描述

**从候补顶点中选出权重最小的顶点。**此处 B 的权重最小,那么路径 A-B 就是从起点 A 到顶点 B 的最短路径。确定了最短路径,移动到顶点B。

在这里插入图片描述

将可以从顶点B直达的顶点设为新的候补顶点,于是顶点 D 和顶点 E 也成为了候补。目前有三个候补顶点 C、D、E。

在这里插入图片描述

同理。在计算B到各顶点值后,比较各点值大小。其中B-C点的权重为8>5,所以不更新。确认了最短路径,移动到顶点D。计算D-E的权重为7>5,发现并不需要更新它。现在,有两个候补顶点(C和E)权重均为5,选择哪一个向下计算都可以。以下先选择C。

在这里插入图片描述

算出F点的权重后,回到E进行计算。

在这里插入图片描述

此时算出G点的权重为14。再次回到F,对F-G的权重进行计算得20>14。故G的最小权重为14。

在这里插入图片描述

最终得到的这颗橙色的树就 是最短路径树,它表示了起点到达各个顶点的最短路径。

比起需要对所有的边都重复计算权重和更新权重的贝尔曼 - 福特算法,狄克斯特拉算法多了一步选择顶点的操作,这使得它在求最短路径上更为高效。

将图的顶点数设为 n、边数设为 m,那么如果事先不进行任何处理,该算法的时 间复杂度就是 O( n²)。不过,如果对数据结构进行优化,那么时间复杂度就会变为 O(m + nlogn)。

有负数权重时不能使用狄克斯特拉算法

不存在负数权重时,更适合使用效率较高的狄克斯特拉算法,而存 在负数权重时,即便较为耗时,也应该使用可以得到正确答案的贝尔曼 - 福特算法。

A*算法

A*(A-Star)算法也是一种在图中求解最短路径问题的算法,由狄克斯特拉算法发展而来。

狄克斯特拉算法会从离起点近的顶点开始,按顺序求出起点到各个顶点的最短路径。也就是说,一些离终点较远的顶点的最短路径也会被计算出来,但这部分其实是无用的。与之不同,A* 就会预先估算一个值,并利用这个值来省去一些无用的计算。

在这里插入图片描述

先使用狄克斯特拉算法来求解以上迷宫的最短路径。

将迷宫看作是一个图,其中每个方块都是一个顶点,各顶点间的距离(权重)都为 1。

在这里插入图片描述

用狄克斯特拉算法求最短路径的结果会如上图所示,方块中的数字表示从起点到该顶点的距离(权重),蓝色和橙色的方块表示搜索过的区域,橙色方块同时还表示从 S 到 G 的最短路径。

狄克斯特拉算法只根据起点到候补顶点的距离来决定下一个顶点。因此,它无法发现蓝色箭头所指的这两条路径其实离终点越来越远,同 样会继续搜索。

在这里插入图片描述

而A* 算法不仅会考虑从起点到候补顶点的距离, 还会考虑从当前所在顶点到终点的估算距离。 这个估算距离可以自由设定,此处我们用的是将顶点到终点的直线距离四舍五入后的值。

由人工预先设定的估算距离被称为**“距离估算值”。如果事先根据已知信息设定合适的距离估算值,再将它作为启发信息辅助计算,搜索就会变得更加高效。这样的算法也成为启发式算法**。

在这里插入图片描述

从起点开始搜索。分别计算起点周围每个顶点的权重。计算方法是“从起点到该顶点的距离”(方块左下)加上 “距离估算值”(方块右下)。

在这里插入图片描述
选择一个权重最小的顶点,用橙色表示,并继续向后搜索。

在这里插入图片描述

按照顺序继续向下搜索。

在这里插入图片描述

在这里插入图片描述

搜索完毕如上图。可以看出基本不回去计算离终点太远的区域。

如果我们能得到一些启发信息,即各个顶点到终点的大致距离(这个距离不需是准确的值)我们就能使用 A* 算法。当然,有时这类信息是完全无法估算的,这时就不能使用 A* 算法。

距离估算值越接近当前顶点到终点的实际值,A* 算法的搜索效率也就越高;反过来,如果距离估算值与实际值相差较大,那么该算法的效率可能会比狄克斯特拉算法的还要低。如果差距再大一些,甚至可能无法得到正确答案。

不过,当距离估算值小于实际距离时,是一定可以得到正确答案的(只是如果没有设定合适的距离估算值,效率会变差)。

A* 算法在游戏编程中经常被用于计算敌人追赶玩家时的行动路线等,但由于该算法的计算量较大,所以可能会使游戏整体的运行速度变慢。因此在实际编程时,需要考虑结合其他算法,或者根据具体的应用场景做出相应调整。

参考资料:我的第一本算法书 (石田保辉 宮崎修一)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/244727.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码上传的gitee平台

1.首先我们访问工作台 - Gitee.com进行注册和登录 2.我们创建一个仓库: 3.在本地创建我们的项目 在这文件夹里面我们打开git bush,执行 一下操作: git init :初始化仓库 git status:检查状态 git add . :将当前文件…

【wimdows电脑上管理员账户与管理员身份的区别】

管理员账户 在控制面板的用户账户中,点击更改账户类型,可以看到目前的账户是“管理员账户”还是“标准账户”。 管理员身份 在快捷方式上右击,可以看到,可以选择以管理员身份运行该软件。 如何查看某个应用是否以管理员身份…

6.Jetson Orin Nano 系统在NVME SSD上备份与恢复

Jetson Orin Nano 系统在NVME SSD上备份与恢复 刚开始我也参考其它博主写的系统备份与恢复,由于我Jetson 的系统盘是1t的,用dd命令拷贝的到另外一个1t的硬盘里面时,总会出现硬盘空间不足的情况出现。只能从小硬盘容量往大硬盘容量拷贝&#…

单通道led线性驱动芯片推荐:SM2082EGS

单通道LED线性驱动芯片是一种用于控制LED灯的芯片,它能够提供恒定的电流输出,从而实现LED灯的稳定亮度调节。这种芯片主要由输入端、控制电路、放大器和输出端构成,通过控制输入端的电压和信号来调节LED的亮度。 单通道led线性驱动芯片推荐&a…

JAVA:乘除窗体的实现

目录 题目要求: 窗口的实现: try 和 catch 的用法: 思路大意: 关键代码的实现: 题目要求: 使用 try 和catch 方法完成乘法除法的异常处理和窗体的实现,如下图所示: 窗口的实…

国际著名书画艺术家敖特:连续三届荣获世界美术大赛金奖

敖特 敖特是一位备受国际认可的蒙古族书画艺术家,以其卓越的才华和杰出的艺术成就而脱颖而出。他的艺术简历显示了他在国内外艺术大赛中多次荣获金奖,并获得了白俄罗斯、俄罗斯等国的最高艺术成就奖项,进一步证明了他在国际艺术界的卓越地位…

MidJourney笔记(7)-Seeds

我相信很多人在使用MidJourney的时候,都会遇到一个问题,就是如何保持生成图像的一致性,或者相对一致性,差异性不是很大。此时,我们就需要引入一个seed值,类似给这个提示词生成的图片做一个id标识。 那这个seed值怎么使用? 其实,在我们每次生成的图片,都有有一个seed值…

【Spring教程27】Spring框架实战:一文教你轻松掌握PostMan工具的安装与使用技巧!轻松搞定API测试!!!

目录 1 PostMan简介2 PostMan安装3 PostMan使用3.1 创建WorkSpace工作空间3.2 发送请求3.3 保存当前请求 4 发送步骤总结 欢迎大家回到《Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博…

【C语言:文件操作】

文章目录 1. 什么是文件1.1为什么有文件?1.2什么是文件1.3文件的分类1.4文件缓冲区 2.文件的打开与关闭2.1文件的打开(fopen)2.2文件的关闭(fclose) 3.顺序读写数据文件3.1读写字符3.2读写字符串3.3格式化读写3.4二进制读写 4.文件的随机读写4.1fseek4.2ftell4.3rew…

【docker】镜像使用(Nginx 示例)

查看本地镜像列表 docker images删除本地镜像 # docker rmi [容器 ID]docker rmi a6bd71f48f68 查找镜像 docker search nginx 参数介绍 NAME: 镜像仓库源的名称DESCRIPTION: 镜像的描述OFFICIAL: 是否 docker 官方发布STARS: 点赞、喜欢AUTOMATED: 自动构建。 拉去镜像 …

shopify商城开发 引用谷歌字体库 fonts.google.com

引用谷歌字体库 https://fonts.google.com/ <link rel"preconnect" href"https://fonts.googleapis.com"> <link rel"preconnect" href"https://fonts.gstatic.com" crossorigin> <link href"https://fonts.goo…

C语言——K /C语言内存函数

一、memcpy 使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num ); • 函数 memcpy 从 source 的位置开始向后复制num个字节的数据到destination指向的内存位置。 • 这个函数在遇到 \0 的时候并不会停下来。 • 如果source和destination有…

了解一下DHCP

DHCP的工作原理 本质&#xff1a; 1、物理网卡自身集成了DHCP的功能&#xff0c;为了请求获取合法、可用的IP 2、DHCP服务端核心功能在于&#xff1a;通过自定义的网段的地址池&#xff0c;来给与新加入的网络环境的设备以租约的方式分配合法IP 1.什么是DHCP 1.1DHCP定义 …

Java获取当前用户当前工作目录

方法一&#xff1a;使用System.getProperty(“user.dir”)函数可以获取用户当前工作目录 例如&#xff0c;Java工程的文件布局如下&#xff1a; 主类文件&#xff0c;获取用户当前的工作目录&#xff1a; package com.thb;public class Test5 {public static void main(Stri…

如何在Kali Linux安装Xrdp+cpolar内网穿透实现远程访问Kali系统

文章目录 前言1. Kali 安装Xrdp2. 本地远程Kali桌面3. Kali 安装Cpolar 内网穿透4. 配置公网远程地址5. 公网远程Kali桌面连接6. 固定连接公网地址7. 固定地址连接测试 前言 Kali远程桌面的好处在于&#xff0c;它允许用户从远程位置访问Kali系统&#xff0c;而无需直接物理访…

HTTP 301错误:永久重定向,大勇的冒险之旅

大家好&#xff0c;我是大勇&#xff0c;一个喜欢冒险的程序员。今天&#xff0c;我要和大家分享一个我在互联网世界中的冒险故事——如何处理HTTP 301错误&#xff1a;永久重定向。 那天&#xff0c;我像往常一样&#xff0c;打开我的代码编辑器&#xff0c;准备开始一天的工…

基于Java SSM框架实现列车火车高铁票务信息管理系统项目【项目源码+论文说明】计算机毕业设计

基于java的SSM框架实现列车火车高铁票务信息管理系统演示 摘要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被…

EasyX图形化学习(二)

1.消息处理---鼠标消息&#xff1a; 1.ExMessage结构体&#xff1a; ExMessage---这个结构体用于保存鼠标消息。 //定义消息结构体变量 ExMessage msg { 0 }; 2.获取消息&#xff1a; &#xff08;1&#xff09;peekmessage函数&#xff1a;用于获取一个消息&#xff0c;…

【算法每日一练]-dfs (保姆级教程 篇7 递推和递归)#三角形个数 #字符串斐波那契

目录 三角形个数 字符串斐波那契 dfs递归解决问题就是把大问题化成小问题&#xff0c;从小问题开始解决 三角形个数 反正就是找规律嘛&#xff1a; 先找正三角的个数&#xff1a; 边长为1&#xff1a;123456 (n-11) 边长为2&#xff1a;12345 (n-21) 边长为3&…

SOLIDWORKS Motion运动平台减速运动分析

SOLIDWROKS motion是SOLIDWORKS中一个高性能的插件&#xff0c;能够帮助设计中完成虚拟样机的仿真分析工具&#xff0c;motion既可以对众多的机械结构进行运动学和动力学仿真&#xff0c;同时也可以反馈机械设备的速度、加速度、作用力等&#xff0c;在SOLIDWROKS motion完成样…