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

问题描述

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

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

问题分析

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

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

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

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

这种搜索图的方法称为广度优先搜索(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 );
            }
    }
}

实现过程

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

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

结合伪代码进行分析:
【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
我们可以通过数据变化表的最终情况来找到这两条路径。

注意,第一行代表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)

运行结果:

与数据变化表的最终情况一致。
这里你可能会问,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 无权最短路径内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python实现Dijkstra算法的最短路径问题

    迪杰斯特拉(Dijkstra)算法主要是针对没有负值的有向图,求解其中的单一起点到其他顶点的最短路径算法. 1 算法原理 迪杰斯特拉(Dijkstra)算法是一个按照路径长度递增的次序产生的最短路径算法.下图为带权值的有向图,作为程序中的实验数据. 其中,带权值的有向图采用邻接矩阵graph来进行存储,在计算中就是采用n*n的二维数组来进行存储,v0-v5表示数组的索引编号0-5,二维数组的值表示节点之间的权值,若两个节点不能通行,比如,v0->v1不能通行,那么graph[0,1]=+∞ (采

  • Python基于Floyd算法求解最短路径距离问题实例详解

    本文实例讲述了Python基于Floyd算法求解最短路径距离问题.分享给大家供大家参考,具体如下: Floyd算法和Dijkstra算法,相信大家都不陌生,在最短路径距离的求解中应该算得上是最为基础和经典的两个算法了,今天就用一点时间来重新实现一下,因为本科的时候学习数据结构才开始接触的这个算法,当时唯一会用的就是C语言了,现在的话,C语言几乎已经离我远去了,个人感觉入手机器学习以来python更得我心,因为太通俗易懂了,带给你的体验自然也是非常不错的. 当然网上 有很多的算法讲解教程,我不会在

  • Python实现迪杰斯特拉算法并生成最短路径的示例代码

    def Dijkstra(network,s,d):#迪杰斯特拉算法算s-d的最短路径,并返回该路径和代价 print("Start Dijstra Path--") path=[]#s-d的最短路径 n=len(network)#邻接矩阵维度,即节点个数 fmax=999 w=[[0 for i in range(n)]for j in range(n)]#邻接矩阵转化成维度矩阵,即0→max book=[0 for i in range(n)]#是否已经是最小的标记列表 dis=[

  • python游戏地图最短路径求解

    一.题目要求 参考下图完成游戏地图中从起点到目标点的最短路径寻找问题. 二.设计思路 先对游戏地图做了几个设定,以矩阵来模拟游戏地图.将可行的区域位置赋值0,障碍区赋值为inf.考虑到地图大小,将起始点和终点区域赋值99. 从Start点A开始向外层扩展,每扩展一层pathlen加一.List Q存储当前需要扩展的点,list P 存储当前扩展层.当扩展到End点B时扩展结束,路径可规划.当Q为空时,本次层扩展结束,检查P,若P非空,从P层向外扩展,若P为空,则End点B无法到达. 寻找最短路径

  • python Dijkstra算法实现最短路径问题的方法

    本文借鉴于张广河教授主编的<数据结构>,对其中的代码进行了完善. 从某源点到其余各顶点的最短路径 Dijkstra算法可用于求解图中某源点到其余各顶点的最短路径.假设G={V,{E}}是含有n个顶点的有向图,以该图中顶点v为源点,使用Dijkstra算法求顶点v到图中其余各顶点的最短路径的基本思想如下: 使用集合S记录已求得最短路径的终点,初始时S={v}. 选择一条长度最小的最短路径,该路径的终点w属于V-S,将w并入S,并将该最短路径的长度记为Dw. 对于V-S中任一顶点是s,将源点到顶点

  • python实现最短路径的实例方法

    最短路径问题(python实现) 解决最短路径问题:(如下三种算法) (1)迪杰斯特拉算法(Dijkstra算法) (2)弗洛伊德算法(Floyd算法) (3)SPFA算法 第一种算法: Dijkstra算法 广度优先搜索解决赋权有向图或者无向图的单源最短路径问题.是一种贪心的策略 算法的思路 声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点s的路径权重被赋为0(dis[s]=0).若对于顶点s存在能直接到达的边(s,m),则把dis[m

  • Python实现的多叉树寻找最短路径算法示例

    本文实例讲述了Python实现的多叉树寻找最短路径算法.分享给大家供大家参考,具体如下: 多叉树的最短路径: 思想: 传入start 和 end 两个 目标值     1 找到从根节点到目标节点的路径     2 从所在路径,寻找最近的公共祖先节点,     3 对最近公共祖先根节点 拼接路径 Python代码: # -*- coding:utf-8 -*- import copy #节点数据结构 class Node(object): # 初始化一个节点 def __init__(self,v

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

    问题描述 现有一个有向无权图.如下图所示: 问题:使用某个顶点s作为输入参数,找出从s到所有其他顶点的最短路径. 说明:因为是无权图,因此我们可以为每台边赋值为1.这里选择v3为s作为起点. 问题分析 此时立刻可以说,从s到v3的最短路径是长为0的路径,标记此信息,得到下图. 现在开始寻找从s出发距离为1的顶点.这些顶点肯定是与s邻接的顶点,很明显,v1,v6从s出发只需要一条边就到了.所以,从s出发距离为1的顶点,为v1,v6. 现在开始寻找从s出发距离为2的顶点.这些顶点肯定是与v1,v6(

  • Java实现利用广度优先遍历(BFS)计算最短路径的方法

    本文实例讲述了Java实现利用广度优先遍历(BFS)计算最短路径的方法.分享给大家供大家参考.具体分析如下: 我们用字符串代表图的顶点(vertax),来模拟学校中Classroom, Square, Toilet, Canteen, South Gate, North Gate几个地点,然后计算任意两点之间的最短路径. 如下图所示: 如,我想从North Gate去Canteen, 程序的输出结果应为: BFS: From [North Gate] to [Canteen]: North Ga

  • Python3遍历目录树实现方法

    本文实例讲述了Python3遍历目录树的方法.分享给大家供大家参考.具体实现方法如下: import os, fnmatch # 检查一个目录,后者某个包含子目录的目录树,并根据某种模式迭代所有文件 # patterns如:*.html,若大小写敏感可写*.[Hh][Tt][Mm][Ll] # single_level 为True表示只检查第一层 # yield_folders 表示是否显示子目录,为False只遍历子目录中的文件, # 但不返回字母名 def all_files(root, p

  • 基于python3 类的属性、方法、封装、继承实例讲解

    Python 类 Python中的类提供了面向对象编程的所有基本功能:类的继承机制允许多个基类,派生类可以覆盖基类中的任何方法,方法中可以调用基类中的同名方法. 对象可以包含任意数量和类型的数据. python类与c++类相似,提供了类的封装,继承.多继承,构造函数.析构函数. 在python3中,所有类最顶层父类都是object类,与java类似,如果定义类的时候没有写出父类,则object类就是其直接父类. 类定义 类定义语法格式如下: class ClassName: <statement

  • Python3实现生成随机密码的方法

    本文实例讲述了Python3实现生成随机密码的方法,在Python程序设计中有着广泛的实用价值.具体方法如下: 本文实例主要实现创建8位随机密码(大小写字母+数字),采用Python3生成了初级算法的随机密码. 主要功能代码如下: __author__ = 'Goopand' import string import random def genPassword(length=8,chars=string.digits+string.ascii_letters): return ''.join(

  • Python3.5常见内置方法参数用法实例详解

    本文实例讲述了Python3.5常见内置方法参数用法.分享给大家供大家参考,具体如下: Python的内置方法参数详解网站为:https://docs.python.org/3/library/functions.html?highlight=built#ascii 1.abs(x):返回一个数字的绝对值.参数可以是整数或浮点数.如果参数是一个复数,则返回它的大小. #内置函数abs() print(abs(-2)) print(abs(4.5)) print(abs(0.1+7j)) 运行结果

  • Python3 修改默认环境的方法

    Mac 环境中既有自带的 Python2.7 也有自己安装的 Python 3.5.1,默认想用 Python3 的环境 1. 添加 Python3 的环境变量 vi ~/.bash_profile # Setting PATH for Python 3.5 # The original version is saved in .bash_profile.pysave PATH="/Library/Frameworks/Python.framework/Versions/3.5/bin:${PA

  • python3转换code128条形码的方法

    这年头如果用 python3 做条形码的,肯定(推荐)用 pystrich . 这货官方文档貌似都没写到支持 Code128 ,但是居然有这个类( Code128Encoder ).... 一些喷墨打印机,如果质量差一点的话,喷出来的条码,会沾到一起,不好识别. 而用 pystrich 的话,会发觉宽度无法调节. 于是想到了用 条形码字体 来自己控制大小,找是找到字库了,但是你会发觉,你生成的东西,无法被扫描识别, 那是因为,这东西得转换后,才能打印啊... 经过千辛万苦,终于找到一篇文章说到转

  • Python3远程监控程序的实现方法

    简述 一开始觉得这个很有趣,然后就想来做一个来玩一下 使用语言: Python3 使用工具:opencv视频监控 + socket数据传输技术 程序检验: 这里我考虑了一下,发现还是没有必要实现封装成可执行文件.还是直接就放代码吧.(先放代码,以后再做解释) 本程序,经过本人修改,保证可以使用 使用要求: Sender代码必须要在一台有摄像头的电脑上运行起来.然后把数据编码,压缩之后,再传给另外一个电脑 Reciever作为接受端,没什么特别的要求. 两个电脑都必须要按转好numpy + ope

  • python3 mmh3安装及使用方法

    mmh3安装方法 哈希方法主要有MD.SHA.Murmur.CityHash.MAC等几种方法.mmh3全程murmurhash3,是一种非加密的哈希算法,常用于hadoop等分布式存储情境中,在anaconda中安装使用命令 pip install mmh3 问题1 报错如下: Microsoft Visual C++ 14.0 is required 显示缺少C++ 14的库文件,选择登录网站  https://visualstudio.microsoft.com/downloads/ 下载

随机推荐