【Algorithms 4】算法(第4版)学习笔记 18 - 4.4 最短路径

文章目录

    • 前言
    • 参考目录
    • 学习笔记
      • 0:引入介绍
      • 1:APIs
      • 1.1:API:加权有向边
      • 1.2:Java 实现:加权有向边
      • 1.3:API:加权有向图
      • 1.4:Java 实现:加权有向图
      • 1.5:API:最短路径
      • 2:最短路径性质
      • 2.1:最短路径的数据结构
      • 2.2:边的松弛 edge relaxation
      • 2.3:最优性条件 optimality conditions
      • 2.4:通用算法 generic shortest-paths algorithm
      • 3:Dijkstra 算法
      • 3.1:demo 演示
      • 3.2:证明
      • 3.3:Java 实现
      • 3.4:计算图生成树
      • 3.5:运行时间
      • 4:无环加权有向图 edge-weighted DAGs
      • 4.1:demo 演示
      • 4.2:证明
      • 4.3:Java 实现
      • 4.4:最长路径
      • 5:负权重 negative weights
      • 5.1:失败尝试
      • 5.2:负权重环 negative cycles
      • 5.3:Bellman-Ford 算法
      • 5.3.1:demo 演示
      • 5.3.2:算法分析
      • 5.4:成本开销小结
      • 6:小结

前言

本篇主要内容包括:APIs最短路径性质Dijkstra 算法无环加权有向图 以及 负权重

参考目录

  • B站 普林斯顿大学《Algorithms》视频课
    (请自行搜索。主要以该视频课顺序来进行笔记整理,课程讲述的教授本人是该书原版作者之一 Robert Sedgewick。)
  • 微信读书《算法(第4版)》
    (本文主要内容来自《4.4 最短路径》)
  • 官方网站
    (有书本配套的内容以及代码)

学习笔记

注1:下面引用内容如无注明出处,均是书中摘录。
注2:所有 demo 演示均为视频 PPT demo 截图。
注3:如果 PPT 截图中没有翻译,会在下面进行汉化翻译,因为内容比较多,本文不再一一说明。

0:引入介绍

加权有向图的最短路径(shortest paths in an edge-weighted digraph):

![image-20240315082159395]

最短路径的应用:

![L15-44ShortestPaths_03]在这里插入图片描述

  • PERT/CPM:计划评审技术/关键路径法
  • 地图路线规划
  • 接缝雕刻(图像缩放中的内容感知算法)
  • 纹理映射(计算机图形学中将图像纹理贴到三维模型表面的技术)
  • 机器人导航技术
  • TeX 中的排版设置
  • 城市交通规划
  • VLSI 芯片的最佳流水线设计
  • 电话营销员操作员调度问题
  • 电信消息的路由选择
  • 网络路由协议(如 OSPF、BGP、RIP)
  • 利用货币兑换市场中的套利机会
  • 根据既定交通拥堵模式确定卡车最优行驶路线

Shortest path is a really interesting and important problem solving model. There’s all kinds of important practical problems that can be recast as shortest paths problems. And because we have efficient solutions to the shortest path, efficient algorithms for finding shortest paths, we have efficient solutions to all these kinds of problems.

最短路径是一个非常有趣且重要的问题解决模型。许多重要的实际问题都可以被重新表述为最短路径问题。正因为如此,我们拥有寻找最短路径的有效解决方案,即高效的最短路径算法,因此也就拥有了解决这类各种问题的有效方法。

最短路径的不同类型:

![L15-44ShortestPaths_04]

顶点类型:

  • 单源:从一个顶点 s 到其他所有顶点。
  • 单汇点:从每个顶点到另一个特定顶点 t。
  • 源汇点:从一个顶点 s 到另一个顶点 t。
  • 全对全:在所有顶点对之间。

边权重限制:

  • 非负权重:所有边的权重都是非负数。
  • 欧几里得权重:边权重基于欧几里得距离。
  • 任意权重:边的权重可以是任意数值。

循环条件:

  • 无有向循环:图中不存在有向循环。
  • 无负权循环:图中不存在权重总和为负值的循环。

简化假设: 从顶点 s 到每个顶点 v 都存在最短路径。

1:APIs

1.1:API:加权有向边

![image-20240315085348075]

1.2:Java 实现:加权有向边

edu.princeton.cs.algs4.DirectedEdge

![image-20240315085631710]

![image-20240315085644190]

1.3:API:加权有向图

![image-20240315085915603]

![image-20240315090301981]

![image-20240315090431816]

1.4:Java 实现:加权有向图

edu.princeton.cs.algs4.EdgeWeightedDigraph

![image-20240315092205110]

![image-20240315092241700]

1.5:API:最短路径

![image-20240315092512628]

2:最短路径性质

2.1:最短路径的数据结构

![L15-44ShortestPaths_14]

目标: 找到从顶点 s 到其他所有顶点的最短路径。

观察结论: 存在一种最短路径树(Shortest Paths Tree, SPT)解法。为什么?

结果: 可以通过两个以顶点索引为键的数组来表示 SPT:

  • distTo[v] 表示从顶点 s 到顶点 v 的最短路径长度。
  • edgeTo[v] 表示从顶点 s 到顶点 v 的最短路径上的最后一段边。

![image-20240315094302501]

对应书本的介绍:

![image-20240315093903240]

2.2:边的松弛 edge relaxation

![L15-44ShortestPaths_16]

对边 e = v → w 进行松弛操作时:

  • distTo[v] 保存已知从源点 s 到顶点 v 的最短路径长度。
  • distTo[w] 保存已知从源点 s 到顶点 w 的最短路径长度。
  • edgeTo[w] 记录已知从源点 s 到顶点 w 的最短路径上最后经过的边。
  • 若通过边 e = v → w 能够到达顶点 w,并且这条路径比之前已知的从 s 到 w 的最短路径更短,则更新 distTo[w] 以及 edgeTo[w]

![image-20240315095849401]

2.3:最优性条件 optimality conditions

![image-20240315100606867]

命题: 设G是一个带权有向图(edge-weighted digraph),则 distTo[] 数组存储的是从源点 s 到各顶点的最短路径距离,当且仅当满足以下条件:

  • distTo[s] = 0,即源点s到自身的最短路径距离为0。
  • 对于每个顶点 v,distTo[v] 表示从源点 s 到顶点 v 的某条路径的长度。
  • 对于每条边 e = v → wdistTo[w] 的值小于等于从源点 s 经由顶点 v 再到顶点 w 的路径长度,即 distTo[w] ≤ distTo[v] + e.weight(),其中 e.weight() 表示边 v → w 的权重。

对应书本命题 P:

![image-20240315100652432]

必要性证明:

![image-20240315101018144]

对应书本的证明:

![image-20240315101424511]

充分性证明:

![image-20240315101504323]

对应书本的证明:

![image-20240315101559185]

2.4:通用算法 generic shortest-paths algorithm

对应书本命题 Q:

![image-20240315102227890]

3:Dijkstra 算法

3.1:demo 演示

![image-20240315103616581]

  • 按照离源点 s 的距离递增顺序考虑顶点(选取具有最低 distTo[] 值的非树顶点)。
  • 将该顶点添加至树结构中,并对其指向的所有边执行松弛操作。

初始状态:

![image-20240315103812262]

距离 s 最近是顶点 0,从顶点 0 开始:

![image-20240315103957761]

对从顶点 0 开始的边进行松弛操作:

![image-20240315104159042]

顶点 0 到 1 为最短路径,继续选择顶点 1:

![image-20240315110732282]

对从顶点 1 开始的边进行松弛操作:

![image-20240315110937592]

![image-20240315111120815]

顶点 0 到 7 为最短路径,继续选择顶点 7:

![image-20240315112458304]

对从顶点 7 开始的边进行松弛操作:

![image-20240315112525900]

![image-20240315112605879]

顶点 0 到 4 为最短路径,继续选择顶点 4:

![image-20240315112740572]

对从顶点 4 开始的边进行松弛操作:

![image-20240315112842144]

![image-20240315112904984]

顶点 4 到 5 为最短路径,继续选择顶点 5:

![image-20240315113029552]

对从顶点 5 开始的边进行松弛操作:

![image-20240315113110077]

![image-20240315113126024]

顶点 5 到 2 为最短路径,继续选择顶点 2:

![image-20240315113207365]

对从顶点 2 开始的边进行松弛操作:

![image-20240315113236950]

![image-20240315113249721]

顶点 2 到 3 为最短路径,继续选择顶点 3:

![image-20240315113329032]

对从顶点 3 开始的边进行松弛操作:

![image-20240315113348502]

![image-20240315113406022]

顶点 2 到 6 为最短路径,继续选择顶点 6:

![image-20240315113446235]

对从顶点 6 开始的边进行松弛操作:

![image-20240315113534275]

s 开始的最短路径树:

![image-20240315113948791]

3.2:证明

![L15-44ShortestPaths_29]

对应书本命题 R:

![image-20240315114148251]

3.3:Java 实现

edu.princeton.cs.algs4.DijkstraSP

![image-20240315115804455]

![image-20240315115855899]

edu.princeton.cs.algs4.DijkstraSP#relax

![image-20240315120026331]

3.4:计算图生成树

![L15-44ShortestPaths_33]

Dijkstra 算法应该相当熟悉吧?

  • Prim 算法在本质上是相同的算法。
  • 两者都属于计算生成树的一类算法。

主要区别在于 选择下一个加入树中的顶点时所依据的规则:

  • Prim 算法选择的是距离当前生成树最近的顶点(通过无向边);
  • 而 Dijkstra 算法选择的是距离源点最近的顶点(通过有向路径)。

注: 深度优先搜索(DFS)和广度优先搜索(BFS)也属于这一类用于生成树或遍历图的算法。

3.5:运行时间

(同 Prim 算法)

![L15-44ShortestPaths_32]

核心要点:

  • 采用数组实现对稠密图(Dense graphs)而言是最佳方案。
  • 对于稀疏图(Sparse graphs),二叉堆在性能上要快得多。
  • 在对性能要求极高的情况下,使用四路堆(4-way heap)是值得投入精力提升性能的。
  • 斐波那契堆在理论上的优越性虽高,但在实际开发中却未必值得进行具体实现。

4:无环加权有向图 edge-weighted DAGs

4.1:demo 演示

![image-20240316134718054]

  • 按拓扑排序考虑顶点。
  • 从该顶点出发对所有指向的边进行松弛操作。

初始状态:

![image-20240316134854048]

首先对顶点进行拓扑排序:

![image-20240316135043894]

从顶点 0 开始,对从顶点 0 开始的边进行松弛操作:

![image-20240316135324509]

继续选择顶点 1,并进行松弛操作:

![image-20240316135515915]

继续选择顶点 4,并进行松弛操作:

![image-20240316141338821]

继续选择顶点 7,并进行松弛操作:

![image-20240316141608117]

继续选择顶点 5,并进行松弛操作:

![image-20240316141644511]

继续选择顶点 2,并进行松弛操作:

![image-20240316141819644]

继续选择顶点 3,并进行松弛操作:

![image-20240316143812156]

继续选择顶点 6,并进行松弛操作:

![image-20240316143839873]

s 开始的最短路径树:

![image-20240316144501557]

4.2:证明

![L15-44ShortestPaths_38]

对应书本命题 S:

![image-20240316145708486]

4.3:Java 实现

edu.princeton.cs.algs4.AcyclicSP

![image-20240316151408099]

![image-20240316151431446]

4.4:最长路径

![L15-44ShortestPaths_46]

带权重有向无环图(DAG)中的最短路径问题:

  • 对所有边的权重取反。
  • 找出这些取反权重后的最短路径。
  • 在得到的结果中再次对边的权重取反。

(等价于:在 relax() 函数中反转相等性判断的方向)

关键点: 拓扑排序算法即使在存在负权边的情况下也能正常工作。

5:负权重 negative weights

5.1:失败尝试

![L15-44ShortestPaths_51]

Dijkstra 算法: 该算法无法处理具有负权重的边。
重赋权重法: 对所有边权重增加一个常数值的方法无效。
结论: 我们需要采用一种不同的算法来解决此问题。

5.2:负权重环 negative cycles

![L15-44ShortestPaths_52]

对应书本定义以及命题 W:

![image-20240316161032461]

![image-20240316161058157]

5.3:Bellman-Ford 算法

![L15-44ShortestPaths_53]

对应书本命题 X:

![image-20240316163337743]

5.3.1:demo 演示

![image-20240316163457806]

重复 V 次:松弛有向图 E 所有边。

初始状态:

![image-20240316163628062]

初始化,将到源的距离设置为 0:

![image-20240316163838365]

对顶点 0 所有有向边进行松弛操作:

![image-20240316164534404]

![image-20240316164759986]

![image-20240316164813178]

对顶点 1 所有有向边进行松弛操作:

![image-20240316164925311]

![image-20240316164943422]

![image-20240316165014037]

对顶点 2 所有有向边进行松弛操作:

![image-20240316165052683]

![image-20240316165128407]

对顶点 3 所有有向边进行松弛操作:

![image-20240316165152695]

对顶点 4 所有有向边进行松弛操作:

![image-20240316165252427]

![image-20240316165320702]

![image-20240316165349289]

对顶点 5 所有有向边进行松弛操作:

![image-20240316165439474]

![image-20240316165504694]

对顶点 7 所有有向边进行松弛操作:

![image-20240316165531693]

![image-20240316165552335]

以上完成第一轮操作。

再次进行松弛操作。

大部分操作与第一轮类似,但也有可以更新的部分:

![image-20240316165907917]

![image-20240316170050428]

同理进行后续的循环:

![image-20240316170146032]

没有更加优化的路径,完成所有松弛操作。

最终得到 s 开始的最短路径树:

![image-20240316170308062]

5.3.2:算法分析

![L15-44ShortestPaths_57]

对应书本命题 Y:

![image-20240316181217238]

5.4:成本开销小结

![L15-44ShortestPaths_59]

  • 注释1: 存在有向循环会使问题求解难度增大。
  • 注释2: 负权重边的存在会使问题变得更加复杂。
  • 注释3: 负权重环会导致问题无法有效解决或无解状态。

6:小结

![L15-44ShortestPaths_65]

非负权重:

  • 在许多应用中出现。
  • Dijkstra 算法的时间复杂度接近线性时间。

无环带权有向图:

  • 在某些应用中出现。
  • 通过拓扑排序算法可以在线性时间内求解。
  • 边的权重可以为负。

负权重和负权重环:

  • 在某些应用中出现。
  • 如果不存在负权重环,可以通过 Bellman-Ford 算法找到最短路径。
  • 若存在负权重环,仍可通过 Bellman-Ford 算法找到一条路径(但可能不是最短路径)。

最短路径问题是广泛应用于问题求解的一个模型。

![image-20240316183053632]

(完)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

android studio设置flutter和dart的sdk配置

提示没有配置dart sdk的时候,其实只需要配置一下flutter的sdk就可以了,因为flutter的安装包里面包含了dart的sdk: 按照提示选中这个flutter的安装包路径就可以了: 并且需要开启windows的开发者开关:start ms-settings:…

Rancher操作手册(v2.7.5-rc1)

1.登录 访问地址:10.66.55.132使用账号和密码登录。初始的页面是英文版本,可以点击左下方改为简体中文 登录成功后可以看到现有的集群。右上角可以进行新集群的创建和导入已有集群。点击箭头所指的蓝色集群名称可以进入集群。 2.集群仪表盘 进入到集…

文字弹性跳动CSS3代码

文字弹性跳动CSS3代码,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果,也可以上传到服务器里面,重定向这个界面 下载地址 文字弹性跳动CSS3代码

神经网络中激活函数的绘制——阶跃函数、sigmoid函数、ReLU函数

一、阶跃函数 import numpy as np import matplotlib.pylab as plt def step_function(x):return np.array(x>0)x np.arange(-5.0,5.0,0.1) y step_function(x) plt.plot(x, y) plt.ylim(-0.1, 1.1) plt.show() 二、sigmoid函数 import numpy as np import matplotlib.p…

Java多线程学习(一)

多线程学习(二):http://t.csdnimg.cn/Q8Koc 目录 1、什么是多线程 2、如何创建多线程(多个方法) 方法一:继承Thread类创建线程 方法二:实现Runnable接口创建线程 方法三、实现Callable接口…

Day46-http和www基础1

Day46-http和www基础1 1. 用户访问网站基本流程2. DNS系统解析基本流程3. DNS功能4. DNS树形结构介绍5. DNS解析流程(核心)6. 查看生产【授权DNS】并设置解析7. dig查看实际DNS解析8. 企业要不要搭建DNS服务器?9. HTTP协议10. HTTP协议版本11…

Kubernetes 编排系统

Kubernetes 编排系统 Kubernetes(简称K8s)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它提供了一种灵活而强大的方式来管理容器化应用程序的生命周期,包括自动化部署、扩展、负载均衡、故障恢复等功能…

16、技巧之九: 修改参数,如何让表格翻页滚动到底部?【Selenium+Python3网页自动化总结】

1、问题提出 在网页配置参数时,输入参数名称搜索,搜出来的同名参数结果有多个,分布在一个表格的不同行,表格是动态加载的,需要滚动鼠标才能把所出参数找出来。用selenium怎么实现这种参数修改? 2、网页元素…

计算机网络 |内网穿透

其实内网穿透,也挺好玩的,如果在大学的时候,那个时候讲计算机网络的老师能横向延展,估计课也会更有趣不少,本来计算机网络这门课就是计算机课程中可玩性最搞的。 只能说,怪可惜的 回到正题,内网…

知名Web3投资基金a16z合伙人Jane Lippencott确认出席Hack.Summit() 2024区块链开发者大会

在区块链技术的风起云涌和Web3生态的蓬勃发展中,知名a16z Crypto的合伙人Jane Lippencott已确认出席即将于2024年4月9日至10日在香港数码港举行的Hack.Summit() 2024区块链开发者大会。作为亚洲首次举办的Hack.Summit(),此次大会将为全球区块链开发者及业…

计算机网络——物理层(数据交换方式)

计算机网络——数据交换方式 提高数据交换方式的必要性电路交换电路交换原理电路交换的阶段建立阶段通信阶段和连接拆除阶段 电路交换的优缺点报文交换什么是报文报文交换的阶段报文交换的优缺点 分组交换分组交换的阶段分组交换的优缺点 数据交换方式的选择数据报方式数据报方…

相机拍照与摄影学基础

1.相机拍照 相机可能形状和大小不同,但基本功能相同,包括快门速度、光圈和感光度,这些是摄影的通用概念。即使是一次性相机也是基于这三个理念工作的。不同类型相机在这三个概念上的唯一区别是你可以控制这些功能的程度。这三个参数被称为相…

【ESP32接入国产大模型之MiniMax】

1. MiniMax 讲解视频: ESP32接入语言大模型之MiniMax MM智能助理是一款由MiniMax自研的,没有调用其他产品的接口的大型语言模型。MiniMax是一家中国科技公司,一直致力于进行大模型相关的研究。 随着人工智能技术的不断发展,自然语…

基于opencv的图像处理系统的设计与实现

概要 随着计算机技术的飞速发展,图像技术在各领域的研究和应用日渐深入和广泛。opencv是近年来推出的开源、免费的计算机视觉库,利用其所包含的函数可以很方便地实现数字图像处理。本文旨在对opencv进行一个快速全面简介,通过介绍图像处理的相关函数,使读…

(一)、机器人时间同步方案分析

1、是否有必要进行时间同步 目前的自动驾驶系统包括 感知、定位、决策规划、控制 等模块,这些模块的正常运行需要依靠各种不同类型的传感器数据的准确 融合。尤其是激光雷达与相机这两种传感器在感、知定位模块中起着至关重要的作用。机械式旋转扫描激光雷达本身较低…

web canvas系列——快速入门上手绘制二维空间点、线、面

文章目录 ⭐前言⭐基本用法💖设置一个 canvas 2D 上下文💖绘制矩形常用方法属性💖绘制一个红蓝交替的矩形 💖绘制路径常用方法属性💖画一个点💖画一条线💖画一个三角形面💖画一个笑脸…

Rust 程序设计语言学习——所有权

这一节主要来学习 Rust 语言的其他特性,所有权、引用与借用、Slice 类型。 1 所有权 Rust 的核心功能(之一)是所有权(ownership)。虽然该功能很容易解释,但它对语言的其他部分有着深刻的影响。 所有程序…

Explain 关键字

优质博文:IT-BLOG-CN explain关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理 SQL 语句的。分析查询语句或表结构的性能瓶颈。执行语句:explain SQL语句。表头信息如下: 一、ID 参数 select 查询的序列号&…

MySQL实现事务隔离的秘诀之锁

在MySQL中,有多种锁类型,我们先了解三种概念的锁,以便对接下来的内容有更好理解。 表级锁(Table Lock):对整个表加锁,其他事务无法修改或读取该表的数据,但可以对其他表进行操作。页…

【数据结构和算法初阶(C语言)】二叉树铺垫--栈帧的创建与销毁--细节全解

前言: 学习这么久以来,可能有很多疑问:局部变量怎么创建的?为什么局部变量的值是随机的?函数是怎么传参的?传参的顺序是怎么样的?形参和实参是什么样的关系?函数调用是怎么做的&…