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): "& ...
随机推荐
- xcode 预编译头文件
xcode 预编译头文件 cocos2d-prefix.pch #import <Foundation/Foundation.h>
- Android 应用开发性能优化完全分析
1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结.我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只 ...
- Linux命令面试常考的简单汇总
1.显示日期与时间的命令:date 2.显示日历的命令:cal 3.简单好用的计算器:bc 4.热键“命令补全或文件补齐”:Tab 5.热键“中断目前程序”:Ctrl+C 6.热键“键盘输入结束(En ...
- [ffmpeg 扩展第三方库编译系列] frei0r mingw32 下编译问题
在编译安装frei0r的时候遇到两个错误地方, 两个都是在install的时候. 一开始编译都很顺利,输入了 make install之后就走开了,回来一看,报错误. 提示mkdir -p //usr ...
- ogg实现oracle到sql server 2005的同步
一.源端(oracle)配置1.创建同步测试表create table gg_user.t01(name varchar(20) primary key);create table gg_user.t ...
- js构造函数式编程
1.函数式编程 //创建和初始化地图函数: function initMap(){ createMap();//创建地图 setMapEvent();//设置地图事件 addMapControl(); ...
- poj 水题系列
题目:http://poj.org/problem?id=3006 筛选法求素数 #include <iostream> #include<cstdio> #include&l ...
- Innodb parent table open时导致crash
case描述: innodb中,父表和子表通过foreign constraint进行关联, 因为在更新数据时需要check 外键constraint,如果父表被大量的子表reference, 那么在 ...
- Terrocotta - 基于JVM的Java应用集群解决方案
前言 越来越多的企业关键应用都必须采用集群技术,实现负载均衡(Load Balancing).容错(Fault Tolerance)和灾难恢复(Failover).以达到系统可用性(High Avai ...
- js jquery版本的 金额千分位转换函数(非正则,效率极高)
没想到js里面没有 金额千分位格式化的处理函数(例:1,234.01 这样的格式),网上搜了一圈,都是使用正则的方式处理的.正则的效率不敢恭维啊,又耗费资源速度又慢(虽然处理起来会直观一些). 因此专 ...