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使用SocketServer模块编写基本服务器程序的教程
Jul 12 Python
python 迭代器和iter()函数详解及实例
Mar 21 Python
python引用(import)某个模块提示没找到对应模块的解决方法
Jan 19 Python
python的schedule定时任务模块二次封装方法
Feb 19 Python
详解python运行三种方式
May 13 Python
解决Django加载静态资源失败的问题
Jul 28 Python
python GUI库图形界面开发之PyQt5 Qt Designer工具(Qt设计师)详细使用方法及Designer ui文件转py文件方法
Feb 26 Python
Python如何解除一个装饰器
Aug 07 Python
matplotlib自定义鼠标光标坐标格式的实现
Jan 08 Python
python读取pdf格式文档的实现代码
Apr 01 Python
python munch库的使用解析
May 25 Python
Python极值整数的边界探讨分析
Sep 15 Python
Python入门之基础语法详解
May 11 #Python
如何利用Matlab制作一款真正的拼图小游戏
Python机器学习之逻辑回归
Python Pandas知识点之缺失值处理详解
Pytorch实现图像识别之数字识别(附详细注释)
浅谈Python基础之列表那些事儿
详解Python牛顿插值法
You might like
php与mysql建立连接并执行SQL语句的代码
2011/07/04 PHP
php遍历所有文件及文件夹的方法深入解析
2013/06/08 PHP
用 Composer构建自己的 PHP 框架之使用 ORM
2014/10/30 PHP
php通过正则表达式记取数据来读取xml的方法
2015/03/09 PHP
php单一接口的实现方法
2015/06/20 PHP
php实现博客,论坛图片防盗链的方法
2016/10/15 PHP
Yii2.0使用阿里云OSS的SDK上传图片、下载、删除图片示例
2017/09/20 PHP
[JS源码]超长文章自动分页(客户端版)
2007/01/09 Javascript
jQuery 图像裁剪插件Jcrop的简单使用
2009/05/22 Javascript
js iframe跨域访问(同主域/非同主域)分别深入介绍
2013/01/24 Javascript
Jquery加载时从后台读取数据绑定到dropdownList实例
2013/06/09 Javascript
特殊情况下如何获取span里面的值
2014/05/20 Javascript
Bootstrap实现响应式导航栏效果
2015/12/28 Javascript
bootstrap快速制作后台界面
2016/12/05 Javascript
PHP实现记录代码运行时间封装类实例教程
2017/05/08 Javascript
js中this对象用法分析
2018/01/05 Javascript
jQuery滑动效果实现方法分析
2018/09/05 jQuery
vue中使用codemirror的实例详解
2018/11/01 Javascript
小程序中this.setData的使用和注意事项
2019/08/28 Javascript
javascript实现点亮灯泡特效示例
2019/10/15 Javascript
vue实现将数据存入vuex中以及从vuex中取出数据
2019/11/08 Javascript
js判断非127开头的IP地址的实例代码
2020/01/05 Javascript
vue接通后端api以及部署到服务器操作
2020/08/13 Javascript
浅谈Vue static 静态资源路径 和 style问题
2020/11/07 Javascript
使用graphics.py实现2048小游戏
2015/03/10 Python
简单讲解Python中的闭包
2015/08/11 Python
Python实现Selenium自动化Page模式
2019/07/14 Python
Python GUI学习之登录系统界面篇
2019/08/21 Python
python__name__原理及用法详解
2019/11/02 Python
Python操作SQLite/MySQL/LMDB数据库的方法
2019/11/07 Python
Python连接字符串过程详解
2020/01/06 Python
django admin管理工具自定义时间区间筛选器DateRangeFilter介绍
2020/05/19 Python
tensorflow使用CNN分析mnist手写体数字数据集
2020/06/17 Python
企业治理工作自我评价
2013/09/26 职场文书
院系推荐意见
2015/06/05 职场文书
利用Python第三方库实现预测NBA比赛结果
2021/06/21 Python