下面是一段由python实现的Dijkstra算法,一些地方的处理实在非常棒,相比于C,代码的数量已经缩减到了60行,所以我想通过本文简单的介绍一下这段代码的细节之处,首先给出源程序:

from sys import argv

def dijkstra_score(G, shortest_distances, v, w):
return shortest_distances[v] + G[v][w] def dijkstra(G, source):
unprocessed = set(G.keys()) # vertices whose shortest paths from source have not yet been calculated
unprocessed.remove(source)
shortest_distances = {source: 0} for i in xrange(len(G) - 1):
# find a vertex with the next shortest path, i.e. minimal Dijkstra score
m, closest_head = float('inf'), 0
for tail in shortest_distances:
for head in G[tail]:
if head in unprocessed:
d = dijkstra_score(G, shortest_distances, tail, head)
if d < m:
m, closest_head = d, head unprocessed.remove(closest_head)
shortest_distances[closest_head] = m # in case G is not fully connected
for vertex in unprocessed:
shortest_distances[vertex] = float('inf') return shortest_distances def get_graph():
filename = argv[1]
graph = {}
with open(filename) as g:
for line in g:
l = line.split()
vertex = int(l.pop(0))
graph[vertex] = {}
for x in l:
adj_vert, distance = map(int, x.split(","))
graph[vertex][adj_vert] = distance
print "Got graph. Ex: line 1:", graph[1]
return graph def main():
G = get_graph()
""" Input is adjacency list on vertices labelled 1 to n, including segment length. Example line of file:
1 3,45 92,4 This means that v. 1 is adjacent to v. 3 with edge length 45 and adjacent to v. 92 with edge length 4.
"""
source = int(raw_input("Enter source vertex: "))
destination_vertices = map(int, raw_input("List destination vertices:\n").split()) distances = dijkstra(G, source) print "From vertex %d:" % source
for vertex in destination_vertices:
print "The distance to vertex %d is %d." % (vertex, distances[vertex]) if __name__ == '__main__':
main()

使用方法:通过外部的文件定义图的构造,每一行的格式为:顶点   到达的顶点,距离    到达的顶点,距离

下面就从每一行值得注意的代码进行分析:

1、图的构造

def get_graph():
filename = argv[1]
graph = {}
with open(filename) as g:
for line in g:
l = line.split()
vertex = int(l.pop(0))
graph[vertex] = {}
for x in l:
adj_vert, distance = map(int, x.split(","))
graph[vertex][adj_vert] = distance
print "Got graph. Ex: line 1:", graph[1]
return graph

这里的图使用邻接表的形式存储,具体的实现采用的python当中的字典,一开始graph为空,graph={}

然后打开存储图的文件,注意这里采用了with语句,相当于try和finally的合体,open函数打开文件并将的返回值给了g。在文件g中的每一行使用split操作,去除空格,得到的l是一个列表,其中第一项就是原点,其余的各项就是原点达到的其他的顶点及其距离。所以将每一个原点放进图graph中作为字典下标,而字典的值仍旧是一个字典,包括了两项,第一项是原点到达的一个顶点,第二项是路径的权值,最后将这两项放入graph中对应的下标构成的字典中。

这样,图就算是构成了,得到的一个字典graph, 例如graph={1:{2,3}}表示的是顶点1到顶点2。

2、单源最短路径

接下来就是通过另一个函数来构造出最短路径了:

def dijkstra(G, source):
unprocessed = set(G.keys()) # vertices whose shortest paths from source have not yet been calculated
unprocessed.remove(source)
shortest_distances = {source: 0} for i in xrange(len(G) - 1):
# find a vertex with the next shortest path, i.e. minimal Dijkstra score
m, closest_head = float('inf'), 0
for tail in shortest_distances:
for head in G[tail]:
if head in unprocessed:
d = dijkstra_score(G, shortest_distances, tail, head)
if d < m:
m, closest_head = d, head unprocessed.remove(closest_head)
shortest_distances[closest_head] = m # in case G is not fully connected
for vertex in unprocessed:
shortest_distances[vertex] = float('inf') return shortest_distances

首先,unprocessed保存了图G中所有顶点的集合,用以表示还没有加入到路径中的顶点,初始化时就是全部的顶点,然后,通过传入函数的source确定开始的顶点,并将该顶点从unprocessed中移除。而记录最短路径的方式则通过shortest_distance这个字典,初始化将自己加入,距离为0。

接下来就是按照Dijkstra算法的步骤一步步进行了:对每一个新加入的顶点找到和这个顶点相邻的边,更新每个顶点的最短距离,这里的实现方式就是通过一个大循环i执行len(G)-1次将每一个顶点都进行处理,每一次处理的开始,将m初始化为无穷大,将closest_head初始化为0,注意,m将会被用来存储最短的距离,而closest_head将会被用来存储最短距离的顶点编号。这里,可以将已经处理好的顶点想象成一个相连的图,而下一个加入到这个图中的顶点就是从原点到剩余顶点距离最短的那一个,具体实现是通过遍历shortest_distance处理完成的顶点,这个字典中每一项都记录了从原点到那个顶点的最短路径,然后图中剩下的没有处理的并且相连的节点,通过dijkstra_score这个函数计算从原点到达那个顶点的距离,将其最小值保存在m中,于是,经过所有的顶点的遍历,找到距离最小的那个点,将其放在shortest_distance中,那么这个顶点就处理完了,接下来就是去处理其他剩余的顶点了。

算法同时也考虑了加入没有连通的情况下的距离,将其设置为无穷大,当然,这里所做的一切都假定所有边的权值为非负,因为假如存在负数的权值,那么最短距离可能不存在。

Dijkstra in python的更多相关文章

  1. Dijkstra算法 python实现

    1.Dijkstra算法的基本实现 \(O(n^2)\) 简介: Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题.迪杰斯特拉算法主要特点是从起始点开始,采用贪 ...

  2. 写出优雅又地道的pythonic代码(转自网络)

    本文是Raymond Hettinger在2013年美国PyCon演讲的笔记(视频, 幻灯片). 示例代码和引用的语录都来自Raymond的演讲.这是我按我的理解整理出来的,希望你们理解起来跟我一样顺 ...

  3. 图:无向图(Graph)基本方法及Dijkstra算法的实现 [Python]

    一般来讲,实现图的过程中需要有两个自定义的类进行支撑:顶点(Vertex)类,和图(Graph)类.按照这一架构,Vertex类至少需要包含名称(或者某个代号.数据)和邻接顶点两个参数,前者作为顶点的 ...

  4. Dijkstra 调度场算法 Python实现 一

    调度场算法(Shunting Yard Algorithm)是一个用于将中缀表达式转换为后缀表达式的经典算法,由 Edsger Wybe Dijkstra 引入,因其操作类似于火车编组场而得名.  — ...

  5. python代码实现dijkstra算法

    求解从1到6的最短路径. python代码实现:(以A-F代表1-6) # Dijkstra算法需要三张散列表和一个存储列表用于记录处理过的节点,如下: processed = [] def buil ...

  6. Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例

    本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个 ...

  7. python数据结构与算法——图的最短路径(Dijkstra算法)

    # Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, ...

  8. 【Python排序搜索基本算法】之Dijkstra算法

    Dijkstra算法和前一篇的Prim算法非常像,区别就在于Dijkstra算法向最短路径树(SPT)中添加顶点的时候,是按照ta与源点的距离顺序进行的.OSPF动态路由协议就是用的Dijkstra算 ...

  9. python利用dijkstra算法求解图中最短距离

    利用dijkstra算法,来完成图中两个顶点间最短的距离,可以直接复制使用,只需要修改参数即可 def dijkstra_raw(edges, from_node, to_node): "& ...

随机推荐

  1. POJ2965——The Pilots Brothers' refrigerator

    The Pilots Brothers' refrigerator Description The game “The Pilots Brothers: following the stripy el ...

  2. JavaBean 内省API BeanUtils工具 泛型 xml xml约束

    1 什么是JavaBean?有何特征? 1)符合特定规则的类    2)JavaBean分二类:     a)侠义的JavaBean         .私有的字段(Field)         .对私 ...

  3. poj 2965 The Pilots Brothers' refrigerator枚举(bfs+位运算)

    //题目:http://poj.org/problem?id=2965//题意:电冰箱有16个把手,每个把手两种状态(开‘-’或关‘+’),只有在所有把手都打开时,门才开,输入数据是个4*4的矩阵,因 ...

  4. Access增删改查 (持续更新中)

    关于Access数据库(2003)的增删改查,其实和Sql大体差不多,但是还有很多不一样的地方.下面列几个容易犯的错误:  1.Access数据库的位置: conn = new OleDbConnec ...

  5. sql 的错误处理功能很弱

    --下面演示了SQL错误处理的脆弱性--邹建 --演示1--测试的存储过程1create proc p1asprint 12/0if @@error<>0print '发生错误1' sel ...

  6. C#中哈希表与List的比较

    简单概念 在c#中,List是顺序线性表(非链表),用一组地址连续的存储单元依次存储数据元素的线性结构. 哈希表也叫散列表,是一种通过把关键码值映射到表中一个位置来访问记录的数据结构.c#中的哈希表有 ...

  7. show slave status中的log_file / log_pos

    在MySQL的master-slave或dual master的架构中,我们经常使用show slave status命令来查看复制状态. 这里涉及几个重要的日志文件和位置: Master_Log_F ...

  8. C# 中winform的一些属性设置

    1 窗体的大小固定住,不能调整其大小 窗体FormBorderStyle 属性设置为 FixedSingle; MaximizeBox 属性设置为false; MinimizeBox  属性设置为  ...

  9. [Tommas] 测试场景 VS 测试用例 哪个更好?(转)

    分享一篇网上别人的感悟:      6年前,我在一家中型跨国公司工作的时候,我建议与其浪费时间在准备充分的测试用例,还不如编写描述测试场景的文档.所有的人都对我的建议.投以烦恼的目光.他们的脸上清晰地 ...

  10. jquery日历datepicker的使用方法

    jquery.ui.datepicker.js 用法: http://blog.csdn.net/zb0567/article/details/7906238   原文  http://blog.cs ...