使用狄克斯特拉算法
狄克斯特拉算法包含4个步骤:
- 找出“最便宜”的节点,即可在最短时间内到达的节点
- 更新该节点的邻居的开销,其含义将稍后介绍
- 重复这个过程,直到对图中的每个节点都这样做了
- 计算最终路径
术语
狄克斯特拉算法用于每条边都有关联数字的图,这些数字称为权重(weight)。带权重的图称为加权图(weighted gragph),不带权重的图称为非加权图(unweighted graph)。
要计算非加权图中的最短路径,可使用广度优先搜索。要计算加权图中的最短路径,可使用狄克斯特拉算法。
在无向图中,每条边都有一个环。狄克斯特拉算法都适用于有向无环图。
狄克斯特拉算法背后的关键理念:找出图中最便宜的节点,并确保没有到该节点的更便宜路径!
如果有负权边,就不能使用狄克斯特拉算法。
以下面的图为例我们看看如何实现狄克斯特拉算法。
```python
#狄克斯特拉算法的实现
#创建图
graph = {}
graph["start"] = {}
graph["start"]["a"] = 6
graph["start"]["b"] = 2
graph["a"] = {}
graph["a"]["fin"] = 1
graph["b"] = {}
graph["b"]["a"] = 3
graph["b"]["fin"] = 5
graph["fin"] = {}
#存储每个节点开销的散列表
infinity = float("inf")
costs = {}
costs["a"] = 6
costs["b"] = 2
costs["fin"] = infinity
#存储父节点的散列表
parents = {}
parents["a"] = "start"
parents["b"] = "start"
parents["fin"] = None
def find_lowest_cost_node(costs,processed) :
lowest_cost = float("inf")
find_lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost < lowest_cost and node not in processed:
lowest_cost = cost
lowest_cost_node = node
return lowest_cost_node
def dij(graph,costs,parents):
#用一个数组记录处理过的节点
processed = []
while len(processed) < len(parents) :
#找出开销最低的节点
node = find_lowest_cost_node(costs,processed)
#获得该节点的开销和邻居
cost = costs[node]
neighbors = graph[node]
#遍历邻居
for n in neighbors.keys():
new_cost = cost + neighbors[n]
if costs[n] > new_cost:
costs[n] = new_cost
parents[n] = node
#将节点标记为处理过的
processed.append(node)
for i in parents.keys():
print(i + "父节点为" + parents[i])
dij(graph,costs,parents)