最短路径问题

概念

  • 可以通过“traceroute”命令来跟踪信息传送的路径:

    traceroute www.lib.pku.edu.cn

  • 可以将互联网路由器体系表示为一个带权边的图

    • 路由器作为顶点,路由器之间网络连接作为边权重可以包括网络连接的速度、网络负载程度、分时段优先级等影响因素
    • 作为一个抽象,我们把所有影响因素合成为单一的权重
  • 解决信息在路由器网络中选择传播速度最快路径的问题, 就转变为在带权图上最短路径的问题。
  • 这个问题与广度优先搜索BFS算法解决的词梯问题相似, 只是在边上增加了权重

    如果所有权重相等,还是还原到词梯问题

Dijkstra算法

思路

Dijkstra算法可用于确定最短路径,它是一种循环算法,可以提供从一个顶点到其他所有顶点的最短路径。这与广度优先搜索非常像。

具体实现上,

  • 在顶点Vertex类中的成员dist用于记录从开始顶点到本顶点的最短带权路径长度(权重之和) , 算法对图中的每个顶点迭代一次
  • 顶点的访问次序由一个优先队列来控制,队列中作为优先级的是顶点的dist属性。
  • 最初, 只有开始顶点dist设为0, 而其他所有顶点dist设为sys.maxsize(最大整数) , 全部加入优先队列。
  • 随着队列中每个最低dist顶点率先出队
  • 并计算它与邻接顶点的权重, 会引起其它顶点dist的减小和修改, 引起堆重排
  • 并据更新后的dist优先级再依次出队

代码

def dijkstra(aGraph, start):
pq = PriorityQueue()
start.setDistance(0)
# 对所有顶点建堆,形成优先队列
pd.buildHeap([v.getDistance(), v for v in aGraph])
while not pq.isEmpty():
# 优先队列出队
currentVert = pq.delMin()
for nextVert in currentVert.getConnections():
newDist = currentVert.getDistance()+currentVert.getWeight(nextVert)
# 修改出队顶点所邻接顶点的dist,并逐个重排队列
if newDist < nextVert.getDistance():
nextVert.setDistance(newDist)
nextVert.setPred(currentVert)
pq.decreaseKey(nextVert, newDist)

算法分析

  • 首先, 将所有顶点加入优先队列并建堆,时间复杂度为O(|V|)
  • 其次, 每个顶点仅出队1次, 每次delMin花费O(log|V|), 一共就是O(|V|log|V|)
  • 另外, 每个边关联到的顶点会做一次decreaseKey操作(O(log|V|)), 一共是O(|E|log|V|)
  • 上 面 三 个 加 在 一 起 , 数 量 级 就 是O((|V|+|E|)log|V|)

小结

  • 需要注意的是, Dijkstra算法只能处理大于0的权重

    如果图中出现负数权重,则算法会陷入无限循环

  • 虽然Dijkstra算法完美解决了带权图的最短路径问题, 但实际上Internet的路由器中采用的是其它算法

  • 其中最重要的原因是, Dijkstra算法需要具备整个图的数据, 但对于Internet的路由器来说, 显然无法将整个Internet所有路由器及其连接信息保存在本地

    • 这不仅是数据量的问题, Internet动态变化的特性也使得保存全图缺乏现实性。
  • 路由器的选径算法(或“路由算法”) 对于互联网极其重要

    https://baike.baidu.com/item/距离向量路由算法


最小生成树 Prim算法

信息广播问题:单播解法

  • 本算法涉及到在互联网中网游设计者和网络收音机所面临的问题:信息广播问题网游需要让所有玩家获知其他玩家所在的位置收音机则需要让所有听众获取直播的音频数据

  • 信息广播问题最简单的解法是由广播源维护一个收听者的列表, 将每条消息向每个

收听者发送一次。如图,每条消息会被发送4次,每个消息都采用最短路径算法到达收听者

  • 路由器A会处理4次相同消息, C仅会处理1次;而B/D位于其它3个收听者的最短路径上, 则各会处理转发3次相同消息
  • 会产生许多额外流量

信息广播问题:洪水解法

  • 信息广播问题的暴力解法, 是将每条消息在路由器间散布出去
  • 所有的路由器都将收到的消息转发到自己相邻的路由器和收听者
  • 显然, 如果没有任何限制, 这个方法将造成网络洪水灾难
  • 很多路由器和收听者会不断重复收到相同的消息, 永不停止!

优化

  • 所以, 洪水解法一般会给每条消息附加一个生命值(TTL:Time To Live) , 初始设置为从消息源到最远的收听者的距离;
  • 每个路由器收到一条消息, 如果其TTL值大于0, 则将TTL减少1, 再转发出去如果TTL等于0了,则就直接抛弃这个消息。
  • TTL的设置防止了灾难发生, 但这种洪水解法显然比前述的单播方法所产生的流量还要大。

信息广播问题:最小生成树

  • 信息广播问题的最优解法, 依赖于路由器关系图上选取具有最小权重的生成树

    (minimum weight spanning tree)

    • 生成树:拥有图中所有的顶点和最少数量的边,以保持连通的子图。
  • 图G(V,E)的最小生成树T, 定义为包含所有顶点V,以及E的无圈子集,并且边权重之和最小

这样信息广播就只需要从A开始, 沿着树的路径层次向下传播就可以达到每个路由器只需要处理1次消息,同时总费用最小

Prim算法

  • 解决最小生成树问题的Prim算法, 属于“贪心算法”, 即每步都沿着最小权重的边向前搜索。
  • 构造最小生成树的思路很简单, 如果T还不是生成树, 则反复做:

    找到一条最小权重的可以安全添加的边,将边添加到树T
  • “可以安全添加”的边, 定义为一端顶点在树中, 另一端不在树中的边, 以便保持树的无圈特性
def prim(G, start):
pq = PriorityQueue()
for v in G:
v.setDistance(sys.maxsize)
v.setPred(None)
start.setDistance(0)
pd.buildHeap([(v.getDistance(), v) for v in G])
while not pq.isEmpty():
# 优先队列出队
currentVert = pq.delMin()
for nextVert in currentVert.getConnections():
newCost = currentVert.getWeight(nextVert)
# 修改出队顶点所邻接顶点的dist,并逐个重排队列
if nextVert in pq and newCost < nextVert.getDistance():
nextVert.setDistance(newCost)
nextVert.setPred(currentVert)
pq.decreaseKey(nextVert, newCost)

【数据结构与算法Python版学习笔记】图——最短路径问题、最小生成树的更多相关文章

  1. 【数据结构与算法Python版学习笔记】引言

    学习来源 北京大学-数据结构与算法Python版 目标 了解计算机科学.程序设计和问题解决的基本概念 计算机科学是对问题本身.问题的解决.以及问题求解过程中得出的解决方案的研究.面对一 个特定问题,计 ...

  2. 【数据结构与算法Python版学习笔记】图——强连通分支

    互联网 我们关注一下互联网相关的非常巨大图: 由主机通过网线(或无线)连接而形成的图: 以及由网页通过超链接连接而形成的图. 网页形成的图 以网页(URI作为id)为顶点,网页内包含的超链接作为边,可 ...

  3. 【数据结构与算法Python版学习笔记】图——拓扑排序 Topological Sort

    概念 很多问题都可转化为图, 利用图算法解决 例如早餐吃薄煎饼的过程 制作松饼的难点在于知道先做哪一步.从图7-18可知,可以首先加热平底锅或者混合原材料.我们借助拓扑排序这种图算法来确定制作松饼的步 ...

  4. 【数据结构与算法Python版学习笔记】图——骑士周游问题 深度优先搜索

    骑士周游问题 概念 在一个国际象棋棋盘上, 一个棋子"马"(骑士) , 按照"马走日"的规则, 从一个格子出发, 要走遍所有棋盘格恰好一次.把一个这样的走棋序列 ...

  5. 【数据结构与算法Python版学习笔记】图——词梯问题 广度优先搜索 BFS

    词梯Word Ladder问题 要求是相邻两个单词之间差异只能是1个字母,如FOOL变SAGE: FOOL >> POOL >> POLL >> POLE > ...

  6. 【数据结构与算法Python版学习笔记】图——基本概念及相关术语

    概念 图Graph是比树更为一般的结构, 也是由节点和边构成 实际上树是一种具有特殊性质的图 图可以用来表示现实世界中很多有意思的事物,包括道路系统.城市之间的航班.互联网的连接,甚至是计算机专业的一 ...

  7. 【数据结构与算法Python版学习笔记】查找与排序——散列、散列函数、区块链

    散列 Hasing 前言 如果数据项之间是按照大小排好序的话,就可以利用二分查找来降低算法复杂度. 现在我们进一步来构造一个新的数据结构, 能使得查找算法的复杂度降到O(1), 这种概念称为" ...

  8. 【数据结构与算法Python版学习笔记】算法分析

    什么是算法分析 算法是问题解决的通用的分步的指令的聚合 算法分析主要就是从计算资源的消耗的角度来评判和比较算法. 计算资源指标 存储空间或内存 执行时间 影响算法运行时间的其他因素 分为最好.最差和平 ...

  9. 【数据结构与算法Python版学习笔记】目录索引

    引言 算法分析 基本数据结构 概览 栈 stack 队列 Queue 双端队列 Deque 列表 List,链表实现 递归(Recursion) 定义及应用:分形树.谢尔宾斯基三角.汉诺塔.迷宫 优化 ...

随机推荐

  1. 手写 lodash/get、lodash/set 方法

    动机:平时写js代码时经常遇到要使用 lodash 中 _.get 和 _.set 的情况,每次使用都要引用 lodash,总感觉很烦,能不能自己实现一个简单的方法来实现一样的功能呢? get 方法实 ...

  2. git02

    Git Gui的使用 Ssh key 介绍及使用 Ssh key介绍 我理解的就是每台电脑上会产生出一个ssh key,然后自己有一个远程账户,但是自己有可能有很多台电脑, 包括家里的电脑还有公司的电 ...

  3. linux网络编程(一)

    ============================================================== 第一天:基本概念.TCP.FTP: =================== ...

  4. 控制台:控制台艺术字 & 为控制台输出增加样式(console.log( ))

    控制台/代码文档LOGO 除了知乎的控制台,大部分的代码文档都有这样的字符logo. 下面这个网站可以自动生成符号艺术字: Text to ASCII Art Generator (TAAG) 控制台 ...

  5. Tomcat部署与优化

    目录: 一.Tomcat概述 二.Tomcat 服务部署 三.Tomcat 虚拟主机配置 四.Tomcat 优化 一.Tomcat概述 Tomcat是Java语言开发的,Tomcat服务器是-个免费的 ...

  6. 【转】shell中的$0 $n $# $* $@ $? $$ 变量 if case for while

    shell中的$0 $n $# $* $@ $? $$  shell 编程 | shift 命令用法笔记 $0当前脚本的文件名 $n传递给脚本或函数的参数.n 是一个数字,表示第几个参数.例如,第一个 ...

  7. electron-vue 开发问题合集

    (一)Found 'electron' but not as a devDependency, pruning anyway 原因:对electron没有严格要求的话可以忽略,不影响打包,但会影响第三 ...

  8. vue-cli3项目中使用vue-ueditor-wrap

    Vue + UEditor + v-model 双向绑定 一.安装 1 npm i vue-ueditor-wrap 2 # 或者 3 yarn add vue-ueditor-wrap 二.下载文件 ...

  9. PHP怎么遍历对象?

    对于php来说,foreach是非常方便好用的一个语法,几乎对于每一个PHPer它都是日常接触最多的请求之一.那么对象是否能通过foreach来遍历呢? 答案是肯定的,但是有个条件,那就是对象的遍历只 ...

  10. PHP中类的自动加载

    在之前,我们已经学习过Composer自动加载的原理,其实就是利用了PHP中的类自动加载的特性.在文末有该系列文章的链接. PHP中类的自动加载主要依靠的是__autoload()和spl_autol ...