Dijkstra in python
下面是一段由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的更多相关文章
- Dijkstra算法 python实现
1.Dijkstra算法的基本实现 \(O(n^2)\) 简介: Dijkstra算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题.迪杰斯特拉算法主要特点是从起始点开始,采用贪 ...
- 写出优雅又地道的pythonic代码(转自网络)
本文是Raymond Hettinger在2013年美国PyCon演讲的笔记(视频, 幻灯片). 示例代码和引用的语录都来自Raymond的演讲.这是我按我的理解整理出来的,希望你们理解起来跟我一样顺 ...
- 图:无向图(Graph)基本方法及Dijkstra算法的实现 [Python]
一般来讲,实现图的过程中需要有两个自定义的类进行支撑:顶点(Vertex)类,和图(Graph)类.按照这一架构,Vertex类至少需要包含名称(或者某个代号.数据)和邻接顶点两个参数,前者作为顶点的 ...
- Dijkstra 调度场算法 Python实现 一
调度场算法(Shunting Yard Algorithm)是一个用于将中缀表达式转换为后缀表达式的经典算法,由 Edsger Wybe Dijkstra 引入,因其操作类似于火车编组场而得名. — ...
- python代码实现dijkstra算法
求解从1到6的最短路径. python代码实现:(以A-F代表1-6) # Dijkstra算法需要三张散列表和一个存储列表用于记录处理过的节点,如下: processed = [] def buil ...
- Python数据结构与算法之图的最短路径(Dijkstra算法)完整实例
本文实例讲述了Python数据结构与算法之图的最短路径(Dijkstra算法).分享给大家供大家参考,具体如下: # coding:utf-8 # Dijkstra算法--通过边实现松弛 # 指定一个 ...
- python数据结构与算法——图的最短路径(Dijkstra算法)
# Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, ...
- 【Python排序搜索基本算法】之Dijkstra算法
Dijkstra算法和前一篇的Prim算法非常像,区别就在于Dijkstra算法向最短路径树(SPT)中添加顶点的时候,是按照ta与源点的距离顺序进行的.OSPF动态路由协议就是用的Dijkstra算 ...
- python利用dijkstra算法求解图中最短距离
利用dijkstra算法,来完成图中两个顶点间最短的距离,可以直接复制使用,只需要修改参数即可 def dijkstra_raw(edges, from_node, to_node): "& ...
随机推荐
- ThinkPHP下隐藏index.php以及URL伪静态
第一种方法: 设置url的重写模式(默认模式是1) 'URL_MODEL' => 2, // URL访问模式,可选参数0.1.2.3,代表以下四种模式: 第二种方法: 使用Apache来进行设 ...
- C++创建一个动态链接库工程
前话 在我们安装一些软件时,进入软件安装目录会经常看到.dll格式文件,系统system目录也存在许多dll文件 在软件游戏(window平台)更新的时候,很大部分是下载dll文件 所以会好奇这是什么 ...
- 统计学习方法笔记--EM算法--三硬币例子补充
本文,意在说明<统计学习方法>第九章EM算法的三硬币例子,公式(9.5-9.6如何而来) 下面是(公式9.5-9.8)的说明, 本人水平有限,怀着分享学习的态度发表此文,欢迎大家批评,交流 ...
- C#创建XML文件并保存
随着XML的普及以及在动态WEB应用程序中大量应用,如何通过.NET创建,删除,修改XML文件变的也来也重要了.一个简单的概念是,XML文件跟大的文本文件并没有什么区别,同时它是先于.NET出现,很多 ...
- Hive 接口介绍(Web UI/JDBC)
Hive 接口介绍(Web UI/JDBC) 实验简介 本次实验学习 Hive 的两种接口:Web UI 以及 JDBC. 一.实验环境说明 1. 环境登录 无需密码自动登录,系统用户名shiyanl ...
- 1126. Magnetic Storms(单调队列)
1126 最简单的单调队列应用吧 单调队列是指在一个队列中各个元素单调 递增(或者递减),并且各个元素的下标单调 递增. 单调队列的大体操作 进队时,将进队的元素为e,从队尾往前扫描,直到找到一个不大 ...
- CodeForces 135 B. Rectangle and Square(判断正方形和 矩形)
题目:http://codeforces.com/problemset/problem/135/B 题意:给8个点 判断能否用 4个点构成正方形,另外4个点构成 矩形. 输出 第一行是正方形 ,第二行 ...
- UVa 10622 (gcd 分解质因数) Perfect P-th Powers
题意: 对于32位有符号整数x,将其写成x = bp的形式,求p可能的最大值. 分析: 将x分解质因数,然后求所有指数的gcd即可. 对于负数还要再处理一下,负数求得的p必须是奇数才行. #inclu ...
- c#字符串及数组操作
字符串操作(取当前时间)string time=convert.tostring(DateTime.Today).split( new char []{' '}); textbox1.text= ...
- Bootstrap 源码解析(转)
1.Bootstrap的作用域 2.Bootstrap的类定义 3.Bootstrap的插件定义 4.Bootstrap的事件代理 5.Bootstrap的对象数据缓存 6.Bootstrap的防冲突 ...