Dijkstra重建图

时间:2016-11-15 09:23:22

标签: python dijkstra

好的,所以我在Python中实现了Djakstra's shortest path algorithm并且它正常工作(距离计算正确),但我希望它也能返回新的优化图。这是我的工作:

nodes = ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I')
graph = {'A': {'B': 4, 'H': 8},
         'B': {'A': 4, 'C': 8, 'H': 11},
         'C': {'B': 8, 'D': 7, 'I': 2, 'F': 4},
         'D': {'C': 7, 'E': 9, 'F': 14},
         'E': {'D': 9, 'F': 10},
         'F': {'E': 10, 'D': 14, 'C': 4, 'G': 2},
         'G': {'F': 2, 'H': 1, 'I': 6},
         'H': {'A': 8, 'B': 11, 'I': 7, 'G': 1},
         'I': {'C': 2, 'H': 7, 'G':6}}



inf = 5000 #truncating inf as 5000
sptset = {} #shortest path tree set (SPT)
main = {} #main dict with nodes and their distances
source = 'A'

#initialization of source (starting point)
for node in nodes:
    main[node] = inf
main[source] = 0
sptset[source] = 0
temp_set = {source: 0}
path = {source: None}

current = None


while len(sptset)<len(nodes):
    path[min(temp_set, key=temp_set.get)] = current
    #keeping track of the path
    current = min(temp_set, key=temp_set.get)
    #choosing the next node to check as the minimum of the mainset 
    #(IF node IS NOT in stpset)
    sptset[current] = main.get(current)
    #adding the current node to stpset

    for neighbor in graph[current].keys():
        #for every adjacent node of the current
        alt = main.get(current) + graph[current].get(neighbor)
        #calculate the distance of current node(from the mainset) + wight to neighbor(from graph)
        if alt < main.get(neighbor):
        #if that sum is less than the distance of neighbor (from the mainset), then update it in mainset
            main[neighbor] = alt


    temp_set = {}
    for key in main.keys():
        if key not in sptset.keys():
            temp_set[key] = main.get(key)
    #this dictionary is being used to reconstruct the mainset WITHOUT the nodes already in stpset
    #(this is done so that the algorithm can be reiterated and a new current node can be chosen)


print path
print sptset

现在路径打印完成后,您可以清楚地知道算法路径,而不是节点的真实路径。如何根据我刚刚计算的距离找出节点的真实路径?

2 个答案:

答案 0 :(得分:0)

每当更新最小距离时,您都需要更新父级。因此,不要在主循环的顶部放置path[min(temp_set, key=temp_set.get)] = current,而是在与距离相同的if块下进行父更新:

if alt < main.get(neighbor):
#if that sum is less than the distance of neighbor (from the mainset), then update it in mainset
    path[neighbor] = current
    main[neighbor] = alt

答案 1 :(得分:0)

您无需存储每个节点的路径:main中已提供该信息。对于具有低连接性的图形,可以根据需要扫描main以重建任何路径:

def parent_node(node):
    neighbors = graph[node]
    if len(neighbors) == 0:
        return None
    best_neighbor = min(neighbors, key=lambda neighbor: main[neighbor])
    if main[best_neighbor] >= main[node]:
        return None
    return best_neighbor

def shortest_path(node):
    path = []
    while node:
        path.append(node)
        node = parent_node(node)
    path.reverse()
    return path

farthest_node = max(graph, key=lambda node: main[node])
print shortest_path(farthest_node)