Esta vez aprenderemos sobre el algoritmo de Dijkstra que combina gráficos y texto
El algoritmo de Dijkstra consta de 4 pasos
(1) Encuentre el nodo más barato, el nodo al que se puede llegar en el menor tiempo
(2) Para los vecinos del nodo, verifique si hay un camino más corto hacia ellos, si lo hay, actualice su costo
(3) Repita esto El proceso hasta que haya hecho esto para cada nodo en el gráfico
(4) Calcule la ruta final
el termino:
El algoritmo de Dijkstra se utiliza para gráficos con números asociados en cada borde. Estos números se denominan pesos. Los gráficos con pesos se denominan gráficos ponderados y los gráficos sin pesos se denominan gráficos no ponderados. (gráfico no ponderado)
Para calcular la distancia más corta de un gráfico no ponderado, se puede utilizar la búsqueda primero en amplitud o el algoritmo de Dijkstra, pero puede haber "bucles"
En el algoritmo de Dijkstra, el camino alrededor del círculo no puede ser el camino más corto
El algoritmo de Dijkstra solo se aplica a gráficos acíclicos dirigidos
El camino más corto no se refiere necesariamente a la distancia física, también puede ser para minimizar una determinada métrica
Lado negativo:
El uso del algoritmo de Dijkstra para gráficos con pesos negativos generará una ruta incorrecta, por lo que si hay bordes de peso negativos, no puede usar el algoritmo de Dijkstra
En un gráfico con bordes de peso negativos, para encontrar el camino más corto, se puede utilizar otro algoritmo: el algoritmo de Bellman-Ford
Caso
Encuentre el costo más pequeño de principio a fin
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
processed = [] # 创建一个数组,用于记录处理过的节点
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 = cost # 将其视为开销最低的节点
lowest_cost_node = node
return lowest_cost_node
node = find_lowest_cost_node(costs) # 在未处理过的节点中找到开销最小的节点
while node is not None:
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) # 将当前的节点标记为处理过的
node = find_lowest_cost_node(costs)
print(f"起点到终点的最小开销为:{costs['fin']}") # 找出接下来要处理的节点并循环