今回は、グラフィックとテキストを組み合わせたDijkstraのアルゴリズムについて学びます。
Dijkstraのアルゴリズムは4つのステップで構成されています
(1)最も安いノード、最短時間で到達できるノードを見つける
(2)ノードの隣接ノードについて、それらへのより短いパスがあるかどうかを確認し、ある場合はそのコストを更新します
(3)これを繰り返しますグラフ内のノードごとにこれを実行するまでのプロセス
(4)最終パスを計算します
用語:
Dijkstraアルゴリズムは、各エッジに番号が関連付けられているグラフに使用されます。これらの番号は重みと呼ばれます。重みのあるグラフは重み付きグラフと呼ばれ、重みのないグラフは重みなしグラフと呼ばれます。 (重み付けされていないグラフ)
重み付けされていないグラフの最短距離を計算するには、幅優先検索またはDijkstraのアルゴリズムのいずれかを使用できますが、「ループ」が存在する場合があります。
Dijkstraのアルゴリズムでは、円の周りのパスを最短パスにすることはできません
Dijkstraのアルゴリズムは、有向非周期グラフにのみ適用されます
最短パスは必ずしも物理的な距離を指すわけではなく、特定のメトリックを最小化することもあります
マイナス面:
負の重みを持つグラフにDijkstraのアルゴリズムを使用すると、間違ったパスが作成されるため、負の重みのエッジがある場合、Dijkstraのアルゴリズムを使用することはできません。
負の重みエッジを持つグラフでは、最短パスを見つけるために、別のアルゴリズムを使用できます-ベルマン-フォードアルゴリズム(ベルマン-フォードアルゴリズム)
場合
最初から最後まで最小のコストを見つける
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']}") # 找出接下来要处理的节点并循环