简述
狄克斯特拉算法用于找到带权图中,某点到其他各点的最短路径(BFS用于找出无权图中的最短路径)
只适用于
- 有向无环图
- 无负权重图,因为狄克斯特拉算法在处理节点时候采用贪心思想,即某节点一旦被处理了,就说明不存在到达该节点更小开销的路径
(存在负权重可以采用贝尔曼·福德算法)
"""
贝尔曼·福德算法
1) 初始化时起点到其他点的距离为对应权重,无法直接到达的点则初始化为∞
2) 起点到自身的距离为0 (D[起点] = 0)
3) 对每条边进行v-1次松弛(v为节点个数)
"""
for i in range(v-1):
# 每条边的起点froms与终点tos
for froms, tos in edges:
# 其中D[i]为起点到i点的距离,graph[froms][tos]为这条边的权重
if D[froms] + graph[froms][tos] < D[tos]:
D[tos] = D[froms] + graph[froms][tos]
# 基本重复上述过程,检查是否存在负循环
for i in range(v-1):
for froms, tos in edges:
# 表示存在负循环
if D[froms] + graph[froms][tos] < D[tos]:
D[tos] = float("-inf")
算法过程
- 每次找出起点到该点开销最小的结点
- 以1中找到的结点作为“跳板”,遍历“跳板”结点的邻居结点,检查是否能更新到达这些邻居结点的更小开销
- 重复1、2两步,直到对图中所有结点都这样做了
costs = {"点": "起点到该点的距离"}
neighbors = {"点": "该点的邻居结点"}
# 图
graph = []
# 在未处理的结点中找出开销最小的
def find_lowest_cost_node(costs):
lowest_cost = float("inf")
lowest_cost_node = None
for node in costs:
cost = costs[node]
if cost < lowest_cost and node not in processed:
lowest_cost = costs
lowest_cost_node = node
return lowest_cost_node
node = find_lowest_cost_node(costs)
# 存储已经处理过的结点
processed = set()
while node:
# 起点到“跳板”结点的开销
cost = costs[node]
# 遍历“跳板”结点的邻居
for neighbor in neighbors[node]:
# 检查是否需要更新
new_cost = cost + graph[node][neighbor]
if new_cost < costs[neighbor]:
costs[neighbor] = new_cost
processed.add(node)
node = find_lowest_cost_node(costs)