python3实现无权最短路径的方法


Posted in Python onMay 12, 2021

问题描述

现有一个有向无权图。如下图所示:

python3实现无权最短路径的方法 

问题:使用某个顶点s作为输入参数,找出从s到所有其他顶点的最短路径。
说明:因为是无权图,因此我们可以为每台边赋值为1。这里选择v3为s作为起点。

问题分析

此时立刻可以说,从s到v3的最短路径是长为0的路径,标记此信息,得到下图。

python3实现无权最短路径的方法 

现在开始寻找从s出发距离为1的顶点。这些顶点肯定是与s邻接的顶点,很明显,v1,v6从s出发只需要一条边就到了。所以,从s出发距离为1的顶点,为v1,v6。

python3实现无权最短路径的方法 

现在开始寻找从s出发距离为2的顶点。这些顶点肯定是与v1,v6(距离为1的顶点)邻接的顶点。发现与v1邻接的顶点为v2,v4,与v6邻接的顶点没有(不能往回走,没有出边)。所以,从s出发距离为2的顶点,为v2,v4。

python3实现无权最短路径的方法 

最后,考察与v2,v4邻接的顶点,即v5,v7。所以,从s出发距离为3的顶点,为v5,v7。

python3实现无权最短路径的方法 

这种搜索图的方法称为广度优先搜索(breadth-first search)。按层处理顶点,距离起点近的顶点先处理,距离起点远的后处理。

伪代码(处理节点)

void unweighted(Vertex s){
    Queue<Vertex> q = new Queue<Vertex>();
    //把每个顶点的距离设为无穷大
    for each Vertex v
        v.dist = INFINITY
    //将起点的距离设为0
    s.dist = 0;
    //起点入队,作为算法的开始
    q.enqueue(s);
    //只要队列不为空,便继续循环
    while( !q.isEmpty() ){
        //获得出队顶点
        Vertex v = q.dequeue();
        //对与v邻接的每个顶点进行处理
        for each Vertex w adjacent to v
            if(w.dist == INFINITY){
                w.dist = v.dist + 1;
                w.path = v;//代表w的上一个经过的顶点为v
                //完成操作后,便入队,以用来接着分析与w邻接的顶点们
                q.enqueue( w );
            }
    }
}

实现过程

python3实现无权最短路径的方法 

python3实现无权最短路径的方法 

从s开始到顶点的距离放到dv列里,pv列用来代表,当前行代表的顶点的上一个经过的顶点。known列代表此顶点已经被处理过了。

初始化时,将起点的距离设置为0,且所有的顶点都不是know的。

python3实现无权最短路径的方法 

结合伪代码进行分析:
【1】当第一次循环中,出队的是v3(每次循环只出队一个顶点)
【2】而第一次循环结束时,就是上表中“v3出队后”的数据情况,如下
【3】此时,对v3的邻接的顶点们都作了处理,所以v3就从F变成了T(即已知)
【4】与v3邻接的顶点v1,v6都作了处理,dv都变成了1,pv都为v3
【5】而因为与v1,v6的邻接顶点都还没有开始处理呢,所以v1,v6的F还不能变成T

得到无权最短路径

通过观察图,可以发现有两条路径长为3的最短路径。
【1】v3 => v1 => v2 => v5
【2】v3 => v1 => v4 => v7
我们可以通过数据变化表的最终情况来找到这两条路径。

python3实现无权最短路径的方法 

注意,第一行代表v1,以此类推。
以找到v3 => v1 => v2 => v5路径为例,过程如下:
【1】找到距离为0的顶点,0在且只在第三行,所以第一个顶点为v3
【2】找到距离为1且pv为v3的顶点,有第一行和第六行,这里必须选一个,这里选第一行,所以第二个顶点为v1
【3】找到距离为2且pv为v1的顶点,有第二行和第四行,这里选第二行,所以第三个顶点为v2
【4】找到距离为3且pv为v2的顶点,只有第五行,所以第四个顶点为v5
【5】找到距离为4且pv为v5的顶点,没有,结束。
其实,以上步骤,是给出了,在对顶点进行数据处理后,找出无权最短路径的算法的思想。
其实可以,维护一些顶点间指针,用来指向下一个顶点,这样就可以用递归的思路来做,从起点开始,每递归到下一层距离dv便加1,用一个中间变量存储经过的顶点,每调用一次递归,便打印这个中间变量,这样,便能得到所有的无权最短路径。
这里得到无权最短路径的伪代码也不给出了,以上分析供大家理解参考。

代码实现

纸上得来终觉浅,绝知此事要躬行!还是觉得用代码实现一遍比较好。

from queue import Queue
class Vertex:
    #顶点类
    def __init__(self,vid,outList):
        self.vid = vid#出边
        self.outList = outList#出边指向的顶点id的列表,也可以理解为邻接表
        self.know = False#默认为假
        self.dist = float('inf')#s到该点的距离,默认为无穷大
        self.prev = 0#上一个顶点的id,默认为0

#创建顶点对象
v1=Vertex(1,[2,4])
v2=Vertex(2,[4,5])
v3=Vertex(3,[1,6])
v4=Vertex(4,[3,5,6,7])
v5=Vertex(5,[7])
v6=Vertex(6,[])
v7=Vertex(7,[6])
#创建一个长度为8的数组,来存储顶点,0索引元素不存
vlist = [False,v1,v2,v3,v4,v5,v6,v7]
def unweighted():
    #起点为v3
    vlist[3].dist = 0
    q = Queue()
    q.put(vlist[3])
    while(not q.empty()):
        v = q.get()#返回并删除队列头部元素
        for w in v.outList:
            if(vlist[w].dist == float('inf')):
                vlist[w].dist = v.dist + 1
                vlist[w].prev = v.vid
                q.put(vlist[w])

unweighted()
print('v1.prev:',v1.prev,'v1.dist',v1.dist)
print('v2.prev:',v2.prev,'v2.dist',v2.dist)
print('v3.prev:',v3.prev,'v3.dist',v3.dist)
print('v4.prev:',v4.prev,'v4.dist',v4.dist)
print('v5.prev:',v5.prev,'v5.dist',v5.dist)
print('v6.prev:',v6.prev,'v6.dist',v6.dist)
print('v7.prev:',v7.prev,'v7.dist',v7.dist)

运行结果:

python3实现无权最短路径的方法 

与数据变化表的最终情况一致。
这里你可能会问,Vertex类的init函数中,明明有know成员,为什么在程序没有使用know成员(在处理节点后,就把该节点的know置为Ture),因为if(vlist[w].dist == float('inf'))的判断就相当于判断节点的know是否为Ture,因为一个已知的节点,它的距离就肯定不是无穷大了。
然后再使用递归,打印出所有可能的最短路径,把以下代码和以上代码合在一起就可以了。

traj_list = [3]#v3是起点直接加上

def print_traj(dist):
    last = traj_list[-1]
    print(traj_list,'该路径的长度为:',vlist[last].dist)
    temp_list = []#存储下一步的选项
    for i in range(1,len(vlist)):
        v = vlist[i]
        if((v.dist==dist) and (v.prev==last)):
            temp_list.append(i)
    if(len(temp_list)==0):
        return#终点
    #递归每个选项
    for i in temp_list:#i为顶点的索引
        traj_list.append(i)
        print_traj(dist+1)
        traj_list.pop()


print_traj(1)

python3实现无权最短路径的方法

到此这篇关于python3实现无权最短路径的方法的文章就介绍到这了,更多相关python3 无权最短路径内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
Python中input和raw_input的一点区别
Oct 21 Python
Python读写配置文件的方法
Jun 03 Python
说一说Python logging
Apr 15 Python
基于python 字符编码的理解
Sep 02 Python
在Python 中实现图片加框和加字的方法
Jan 26 Python
Python 控制终端输出文字的实例
Jul 12 Python
python 实现多线程下载m3u8格式视频并使用fmmpeg合并
Nov 15 Python
使用Django清空数据库并重新生成
Apr 03 Python
tensorflow模型的save与restore,及checkpoint中读取变量方式
May 26 Python
浅谈OpenCV中的新函数connectedComponentsWithStats用法
Jul 05 Python
pytorch学习教程之自定义数据集
Nov 10 Python
教你怎么用python selenium实现自动化测试
May 27 Python
Python入门之基础语法详解
May 11 #Python
如何利用Matlab制作一款真正的拼图小游戏
Python机器学习之逻辑回归
Python Pandas知识点之缺失值处理详解
Pytorch实现图像识别之数字识别(附详细注释)
浅谈Python基础之列表那些事儿
详解Python牛顿插值法
You might like
PHP 代码规范小结
2012/03/08 PHP
iis 7下安装laravel 5.4环境的方法教程
2017/06/14 PHP
PHP多进程通信-消息队列使用
2019/03/08 PHP
PHP的new static和new self的区别与使用
2019/11/27 PHP
Auntion-TableSort国人写的一个javascript表格排序的东西
2007/11/12 Javascript
jQuery表单获取和失去焦点输入框提示效果的实例代码
2013/08/01 Javascript
jquery将一个表单序列化为一个对象的方法
2014/01/03 Javascript
jquery制作弹窗提示窗口代码分享
2014/03/02 Javascript
nodejs 实现模拟form表单上传文件
2014/07/14 NodeJs
js实现照片墙功能实例
2015/02/05 Javascript
详解AngularJS的通信机制
2015/06/18 Javascript
AngularJs html compiler详解及示例代码
2016/09/01 Javascript
js实现获取鼠标当前的位置
2016/12/14 Javascript
js前端日历控件(悬浮、拖拽、自由变形)
2017/03/02 Javascript
实现div内部滚动条滚动到底部和顶部的代码
2017/11/15 Javascript
解决layer弹层遮罩挡住窗体的问题
2018/08/17 Javascript
jquery绑定事件 bind和on的用法与区别分析
2020/05/22 jQuery
实例讲解JavaScript 计时事件
2020/07/04 Javascript
express异步函数异常捕获示例详解
2020/11/30 Javascript
Python使用os模块和fileinput模块来操作文件目录
2016/01/19 Python
对python3中, print横向输出的方法详解
2019/01/28 Python
pytorch 模型可视化的例子
2019/08/17 Python
python 内置函数汇总详解
2019/09/16 Python
Python字符串hashlib加密模块使用案例
2020/03/10 Python
Ubuntu中配置TensorFlow使用环境的方法
2020/04/21 Python
Tensorflow实现将标签变为one-hot形式
2020/05/22 Python
python字符串的index和find的区别详解
2020/06/20 Python
Python如何使用vars返回对象的属性列表
2020/10/17 Python
python3访问字典里的值实例方法
2020/11/18 Python
英语师范专业毕业生自荐信
2013/09/21 职场文书
城市精细化管理实施方案
2014/03/04 职场文书
2014年国庆标语
2014/06/30 职场文书
2014老师三严三实对照检查材料思想汇报
2014/09/18 职场文书
redis连接被拒绝的解决方案
2021/04/12 Redis
对讲机知识
2022/04/07 无线电
Flutter Navigator 实现路由传递参数
2022/04/22 Java/Android