Dijkstra's Algoritm
很多问题都可以抽象为shortest path in a weighted graph。所以掌握一种shortest path的算法还是很重要的。比如这道面经题目(找P5那道题)我是面经。 这里我们提供一种比较简单方便实现的Dijstra algorithm。不是最优的,还有很多优化空间。
Dijkstra's algorithm的思想是。从start point开始,然后把周围能reach到的点存到Queue里面。然后每次取cost最小的那个point来继续traverse这个graph。遇到的每一个点,先检查是否在Q中,不在的话就加进去,在的话就与Q中的点进行比较,如果cost更小就更新Q里面的cost。然后再取一个最短的出来继续算。这样是可以保证最终start到每一个点的cost最小。
好吧我觉得我没有讲清楚,anyway。我们还是看代码吧,我的Q可以用hashed priority queue进行优化。这里我先不管了哈。
class Solution(object):
def dijkstra(self, graph, start, end):
D = {} # distance of the node
P = {} # parent of the node
Q = {} # Q for get the min
Q[start] = 0
while Q:
v = self.get_min(Q) # get the min vertice
D[v] = Q[v]
children = graph[v]
for c in children: # relax each child
dist = Q[v]+children[c]
if c in D:
if dist<D[c]:
raise ValueError
elif c not in Q or dist<Q[c]:
Q[c] = dist
P[c] = v
del Q[v]
path = []
res = D[end]
while end in P:
path.append(end)
end = P[end]
path.append(end)
return path[::-1], res
def get_min(self, Q):
m = (None, float('inf'))
for k in Q:
if Q[k]<m[1]:
m = (k, Q[k])
return m[0]
# example, CLR p.528
G = {'s': {'u':10, 'x':5},
'u': {'v':1, 'x':2},
'v': {'y':4},
'x':{'u':3,'v':9,'y':2},
'y':{'s':7,'v':6}}
so = Solution()
print so.dijkstra(G, 's', 'v')
另外一种实现方法.
import sys
def min_dist(dist, visited, n):
min_val = sys.maxint
min_idx = 0
for i in xrange(n):
if not visited[i] and dist[i] <= min_val:
min_val, min_idx = dist[i], i
return min_idx
def dijkstra(graph, src, des):
n = len(graph)
dist = [sys.maxint] * n
dist[src] = 0
visited = [False] * n
for _ in xrange(n):
i = min_dist(dist, visited, n)
visited[i] = True
if i == des:
return dist[i]
for j in xrange(n):
if (not visited[j] and graph[i][j] and dist[i] != sys.maxint and
dist[i] + graph[i][j] < dist[j]):
dist[j] = dist[i] + graph[i][j]
graph = [[0, 3, 2],[5, 0, 2],[1, 6, 0]]
src, des = 2, 1
print("length of the shortest path from #%d to #%d: %d" \
% (src, des, dijkstra(graph, src, des)))