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): "& ...
随机推荐
- PHP开发工具介绍之zendStudio
1.PHP开发工具介绍之zendStudio 下载:进入官网:http://www.zend.com/en/products/studio 选择下载安装 注意这里的工作空间要和你Apache的工作目录 ...
- jquery.cookie.js使用介绍
Cookies概述: Cookies是一种能够让网站服务器把少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术.Cookies是当你浏览某网站时,由Web服务器置于你硬盘上的一个非 ...
- 用QT创建新风格: QStyle
转贴: http://hi.baidu.com/yjj2008/blog/item/6cd4a1892ef0d4b60f2444a5.html 本文介绍了如何使用qt提供的接口来设计自己的GUI风格( ...
- 面试常考的数据结构Java实现
1.线性表 2.线性链表 3.栈 4.队列 5.串 6.数组 7.广义表 8.树和二叉树 的结点),并且,二叉树的子树有左右之分,其次序不能任意颠倒. 二叉树的性质: :在二叉树的第 i 层上至多有2 ...
- Regular Ball Super Ball
Description: Regular Ball Super Ball Create a class Ball. Ball objects should accept one argument fo ...
- 1019.Line Painting(线段树 离散化)
1019 离散化都忘记怎么写了 注意两个端点 离散化后用线段树更新区间 混色为-1 黑为2 白为1 因为N不大 最后直接循环标记这一段的颜色查找 #include <iostream> ...
- JXL读取Excel日期时间不准确
XL读取Excel日期时间多出了8个小时. Cell c = rs.getCell(j, i); if (c.getType() == CellType.DAT ...
- POJ3921
搜索 每次找出最短路 如果小于等于k 那么必定这里有一点是要被删掉的 枚举这个最短路径上的每一个点 (一般不会超过20) 将其相邻边删除 用dijskra求最短路径并且保存即可 深度搜索 #inclu ...
- Webform——Repeater多表联合显示
对于一个表里,通过外键连接如何显示另一个表的数据,前Winform里可以用封装类来实现. 对于Webform,可以用封装类,也可以用Repeater的ItemDataBound事件(//在项被绑定数据 ...
- UVa 1451 (数形结合 单调栈) Average
题意: 给出一个01串,选一个长度至少为L的连续子串,使得串中数字的平均值最大. 分析: 能把这道题想到用数形结合,用斜率表示平均值,我觉得这个想法太“天马行空”了 首先预处理子串的前缀和sum,如果 ...