この記事では、最も一般的に知られている最短パス アルゴリズムの 1 つ、つまり 1956 年にオランダのコンピュータ科学者エドガー W. ダイクストラによって開発されたダイクストラの最短パス アルゴリズムについて説明します。さらに、このアルゴリズムの複雑さの分析を行い、他の最短経路アルゴリズムとどのように異なるかを確認してください。
目次
- ダイクストラのアルゴリズム
- ダイクストラアルゴリズムの必要性(目的と使用例)
- ダイクストラのアルゴリズムは有向グラフと無向グラフの両方で機能しますか?
- ダイクストラアルゴリズムのアルゴリズム
- ダイクストラのアルゴリズムはどのように機能するのでしょうか?
- ダイクストラアルゴリズムの擬似コード
- ダイクストラのアルゴリズムの実装:
- ダイクストラのアルゴリズムとベルマンフォードのアルゴリズム
- ダイクストラのアルゴリズムとフロイド・ウォーシャルのアルゴリズム
- ダイクストラのアルゴリズムと A* アルゴリズム
- ダイクストラアルゴリズムの練習問題
- 結論:

ダイクストラのアルゴリズム:
ダイクストラのアルゴリズム は、グラフ内の非負のエッジ重みを持つ多くの単一ソース最短経路問題を解くための一般的なアルゴリズムです。つまり、グラフ上の 2 つの頂点間の最短距離を見つけるアルゴリズムです。オランダのコンピューター科学者によって考案されました エドガー・W・ダイクストラ 1956年に。
このアルゴリズムは、訪問済みの頂点のセットと未訪問の頂点のセットを維持します。これはソース頂点から開始し、ソースからの暫定的な距離が最小の未訪問の頂点を繰り返し選択します。次に、この頂点の近隣を訪問し、より短いパスが見つかった場合は暫定的な距離を更新します。このプロセスは、目的の頂点に到達するか、到達可能な頂点をすべて訪問し終わるまで続きます。
ダイクストラアルゴリズムの必要性(目的と使用例)
ダイクストラのアルゴリズムは、2 点間の最短経路を見つけることが重要な多くのアプリケーションで必要になります。
例えば , コンピュータ ネットワークのルーティング プロトコルで使用でき、地図システムでも出発地と目的地間の最短経路を見つけるために使用されます (「 Google マップはどのように機能しますか? )
ダイクストラのアルゴリズムは有向グラフと無向グラフの両方で機能しますか?
はい , ダイクストラのアルゴリズムは、エッジの重みが負ではなく接続されているという要件を満たしている限り、あらゆる種類のグラフで動作するように設計されているため、有向グラフと無向グラフの両方で動作します。
- 有向グラフでは、 各エッジには方向があり、エッジによって接続されている頂点間の移動方向を示します。この場合、アルゴリズムは最短パスを検索するときにエッジの方向に従います。
- 無向グラフでは、 エッジには方向がなく、アルゴリズムは最短パスを検索するときにエッジに沿って前方にも後方にも移動できます。
ダイクストラアルゴリズムのアルゴリズム:
- ソース ノードを現在の距離 0 でマークし、残りのノードを無限大でマークします。
- 現在の距離が最も小さい未訪問ノードを現在のノードとして設定します。
- 各近傍について、現在のノードの N に、0->1 を接続するエッジの重みを使用して隣接ノードの現在の距離を加算します。現在のノードの距離より小さい場合は、それを新しい現在の N の距離として設定します。
- 現在のノード 1 を訪問済みとしてマークします。
- 未訪問のノードがある場合は、ステップ 2 に進みます。
ダイクストラのアルゴリズムはどのように機能するのでしょうか?
以下の例を使用して、ダイクストラのアルゴリズムがどのように機能するかを見てみましょう。
ダイクストラのアルゴリズムは、ノード 0 からグラフ内の他のすべてのノードへの最短パスを生成します。
以下のグラフを考えてみましょう。
ダイクストラのアルゴリズム
このアルゴリズムは、ノード 0 からグラフ内の他のすべてのノードへの最短パスを生成します。
このグラフでは、エッジの重みが 2 つのノード間の距離を表すと仮定します。
日付を文字列にフォーマットするからの最短パスがあることがわかります。
ノード 0 からノード 1 まで
ノード 0 からノード 2 まで
ノード 0 からノード 3 まで
ノード 0 からノード 4 まで
ノード0からノード6まで。最初に、以下に示す一連のリソースがあります。
- ソース ノードからそれ自体までの距離は 0 です。この例では、ソース ノードは 0 です。
- ソース ノードから他のすべてのノードまでの距離は不明なので、すべてのノードを無限としてマークします。
例: 0 -> 0、1 -> ∞、2 -> ∞、3 -> ∞、4 -> ∞、5 -> ∞、6 -> ∞。
- また、未訪問のノードまたはマークされていないノードを追跡する未訪問の要素の配列もあります。
- すべてのノードが訪問済みとしてマークされ、ノード間の距離がパスに追加されると、アルゴリズムは完了します。 未訪問のノード:- 0 1 2 3 4 5 6.
ステップ1: ノード 0 から開始し、下の画像で確認できるように、ノードを訪問済みとしてマークします。訪問済みのノードは赤色でマークされます。
ダイクストラのアルゴリズム
ステップ2: 隣接するノードを確認します。次に、選択肢 (距離 2 のノード 1 を選択するか、距離 6 のノード 2 を選択するかのいずれか) を選択し、最小距離のノードを選択する必要があります。このステップでは ノード1 はノードに隣接する最小距離なので、訪問済みとしてマークし、距離を合計します。
距離: ノード 0 -> ノード 1 = 2
ダイクストラのアルゴリズム
ステップ 3: 次に、前に移動して、隣接するノード (ノード 3) を確認します。そのため、そのノードを訪問済みとしてマークし、距離を合計します。距離は次のようになります。
距離: ノード 0 -> ノード 1 -> ノード 3 = 2 + 5 = 7
ダイクストラのアルゴリズム
ステップ 4: ここでも隣接するノードには 2 つの選択肢があるため (距離 10 のノード 4 を選択することも、距離 15 のノード 5 を選択することもできます)、最小距離のノードを選択します。このステップでは ノード4 はノードに隣接する最小距離なので、訪問済みとしてマークし、距離を合計します。
距離: ノード 0 -> ノード 1 -> ノード 3 -> ノード 4 = 2 + 5 + 10 = 17
ダイクストラのアルゴリズム
ステップ5: もう一度、前に移動して、隣接するノードを確認します。 ノード6 ので、訪問済みとしてマークし、距離を合計すると、距離は次のようになります。
それ以外の場合は Java距離: ノード 0 -> ノード 1 -> ノード 3 -> ノード 4 -> ノード 6 = 2 + 5 + 10 + 2 = 19
ダイクストラのアルゴリズム
したがって、ソース頂点からの最短距離は 19 であり、これが最適な距離です。
ダイクストラアルゴリズムの擬似コード
関数ダイクストラ(グラフ、ソース):
// すべてのノードまでの距離を無限大、ソース ノードまでの距離を 0 に初期化します。距離 = マップ (すべてのノード -> 無限大)
距離 = 0
// 訪問先ノードの空のセットと優先キューを初期化して、訪問先ノードを追跡します。
訪問済み = 空のセット
キュー = 新しい PriorityQueue()
queue.enqueue(ソース, 0)Javaでソートされた配列リスト// すべてのノードにアクセスするまでループします。
キューが空ではない場合:
// 優先キューからの距離が最も小さいノードをデキューします。
current = queue.dequeue()// ノードがすでに訪問されている場合はスキップします。
現在訪問中の場合:
続く// ノードを訪問済みとしてマークします。
訪問済み.追加(現在)// すべての隣接ノードをチェックして、それらの距離を更新する必要があるかどうかを確認します。
Graph.neighbors(current) のネイバーの場合:
// 現在のノードを通る隣接ノードまでの仮の距離を計算します。
暫定_距離 = 距離[現在] + Graph. distance(現在、近傍)// 仮の距離が近隣までの現在の距離より小さい場合は、距離を更新します。
暫定距離の場合
距離[隣接] = 暫定距離// 将来の訪問を検討するために、近隣の新しい距離をキューに入れます。
queue.enqueue(近隣、距離[近隣])// ソースからグラフ内の他のすべてのノードまでの計算された距離を返します。
往復距離
ダイクストラのアルゴリズムの実装:
ダイクストラのアルゴリズムを実装するにはいくつかの方法がありますが、最も一般的な方法は次のとおりです。
- 優先キュー (ヒープベースの実装):
- 配列ベースの実装:
1. priority_queue (ヒープ) を使用したダイクストラの最短パス アルゴリズム
この実装では、グラフとグラフ内のソース頂点が与えられ、ソースから特定のグラフ内のすべての頂点までの最短パスを見つけます。
例:
入力: ソース = 0
例
出力: バーテックス
ソースからの頂点の距離
0 -> 0
1 -> 2
2 -> 6
3 -> 7
4 -> 17
5 -> 22
6 -> 19
上記の考え方に基づいたアルゴリズムは次のとおりです。
- 距離値と優先キューを初期化します。
- 送信元ノードを距離 0 の優先キューに挿入します。
- 優先キューが空でない場合:
- 優先キューからの距離が最小となるノードを抽出します。
- より短いパスが見つかった場合は、隣接するパスの距離を更新します。
- 更新されたネイバーをプライオリティ キューに挿入します。
以下は、上記のアプローチの C++ 実装です。
C++ // Program to find Dijkstra's shortest path using // priority_queue in STL #include using namespace std; #define INF 0x3f3f3f3f // iPair ==>整数ペア typedef ペア iペア; // このクラスは、 // 隣接リスト表現を使用して有向グラフを表します。 class Graph { int V; // 頂点の数 // 重み付きグラフでは、すべてのエッジ リストの頂点と // 重みのペアを保存する必要があります>* 形容詞;パブリック: グラフ(int V); // コンストラクター // グラフにエッジを追加する関数 void addEdge(int u, int v, int w); // s からの最短パスを出力します voidshortPath(int s); }; // 隣接リストにメモリを割り当てます Graph::Graph(int V) { this->V = V; adj = 新しいリスト [V]; void Graph::addEdge(int u, int v, int w) { adj[u].push_back(make_pair(v, w)); adj[v].push_back(make_pair(u, w)); } // src から他のすべての頂点までの最短パスを出力します void Graph::shortestPath(int src) { // 前処理中の頂点を格納する優先キューを作成します。これは C++ の奇妙な構文です。 // この構文の詳細については、以下のリンクを参照してください // https://www.techcodeview.com priority_queue 、より大きい > pq; // 距離のベクトルを作成し、 // すべての距離を無限 (INF) ベクトルとして初期化します。 dist(V, INF); // ソース自体を優先キューに挿入し、 // その距離を 0 として初期化します。 pq.push(make_pair(0, src)); 距離[ソース] = 0; /* 優先キューが空になる (またはすべての距離が確定しない) までループします */ while (!pq.empty()) { // ペアの最初の頂点が最小距離です // 頂点を優先キューから抽出します。 // 頂点ラベルはペアの 2 番目に格納されます ( // 頂点を維持するには、この方法で行う必要があります // ソートされた距離 (距離はペアの // 最初の項目である必要があります) int u = pq.top().second; pq.pop(); // 'i' は頂点リストのすべての隣接する頂点を取得するために使用されます。>::反復子 i; for (i = adj[u].begin(); i != adj[u].end(); ++i) { // u に隣接する現在の // 頂点ラベルと重みを取得します。 int v = (*i).first; int 重み = (*i).秒; // u を介して v へのショートパスがある場合。 if (dist[v]> dist[u] + Weight) { // v の距離を更新 dist[v] = dist[u] + Weight; pq.push(make_pair(dist[v], v)); } } } // dist[] に格納されている最短距離を出力します printf('ソースからの頂点距離
'); for (int i = 0; i< V; ++i) printf('%d %d
', i, dist[i]); } // Driver program to test methods of graph class int main() { // create the graph given in above figure int V = 7; Graph g(V); // making above shown graph g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); return 0; }>
ジャワ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.PriorityQueue; public class DijkstraAlgoForShortestDistance { static class Node implements Comparable{ テレビで; 整数距離; public Node(int v, int distance) { this.v = v; this. distance = 距離; @Override public int CompareTo(Node n) { if (this. distance<= n.distance) { return -1; } else { return 1; } } } static int[] dijkstra( int V, ArrayList >> adj, int S) { boolean[] 訪問 = new boolean[V]; ハッシュマップ マップ = 新しい HashMap(); 優先キューq = 新しいPriorityQueue(); map.put(S, 新しいノード(S, 0)); q.add(新しいノード(S, 0)); while (!q.isEmpty()) { ノード n = q.poll(); int v = n.v; int 距離 = n.距離; 訪問[v] = true; 配列リスト > adjList = adj.get(v); for (配列リスト adjLink : adjList) { if (visited[adjLink.get(0)] == false) { if (!map.containsKey(adjLink.get(0))) { map.put( adjLink.get(0), new Node (v, 距離 + adjLink.get(1))); } else { ノード sn = map.get(adjLink.get(0)); if (距離 + adjLink.get(1)< sn.distance) { sn.v = v; sn.distance = distance + adjLink.get(1); } } q.add(new Node(adjLink.get(0), distance + adjLink.get(1))); } } } int[] result = new int[V]; for (int i = 0; i < V; i++) { result[i] = map.get(i).distance; } return result; } public static void main(String[] args) { ArrayList >> adj = 新しい ArrayList(); ハッシュマップ >> マップ = 新しい HashMap(); int V = 6; int E = 5; int[] u = { 0, 0, 1, 2, 4 }; int[] v = { 3, 5, 4, 5, 5 }; int[] w = { 9, 4, 4, 10, 3 }; for (int i = 0; i< E; i++) { ArrayList エッジ = 新しい ArrayList(); エッジ.add(v[i]); エッジ.add(w[i]); 配列リスト > adjList; if (!map.containsKey(u[i])) { adjList = new ArrayList(); } else { adjList = map.get(u[i]); adjList.add(エッジ); map.put(u[i], adjList); 配列リスト エッジ2 = 新しいArrayList(); edge2.add(u[i]); edge2.add(w[i]); 配列リスト > adjList2; if (!map.containsKey(v[i])) { adjList2 = new ArrayList(); else { adjList2 = map.get(v[i]); adjList2.add(edge2); map.put(v[i], adjList2); } for (int i = 0; i< V; i++) { if (map.containsKey(i)) { adj.add(map.get(i)); } else { adj.add(null); } } int S = 1; // Input sample //[0 [[3, 9], [5, 4]], // 1 [[4, 4]], // 2 [[5, 10]], // 3 [[0, 9]], // 4 [[1, 4], [5, 3]], // 5 [[0, 4], [2, 10], [4, 3]] //] int[] result = DijkstraAlgoForShortestDistance.dijkstra( V, adj, S); System.out.println(Arrays.toString(result)); } }> パイソン # Python implementation of Dijkstra Algorithm import heapq class Node: def __init__(self, v, distance): self.v = v self.distance = distance def __lt__(self, other): return self.distance < other.distance def dijkstra(V, adj, S): visited = [False] * V map = {} q = [] map[S] = Node(S, 0) heapq.heappush(q, Node(S, 0)) while q: n = heapq.heappop(q) v = n.v distance = n.distance visited[v] = True adjList = adj[v] for adjLink in adjList: if not visited[adjLink[0]]: if adjLink[0] not in map: map[adjLink[0]] = Node(v, distance + adjLink[1]) else: sn = map[adjLink[0]] if distance + adjLink[1] < sn.distance: sn.v = v sn.distance = distance + adjLink[1] heapq.heappush(q, Node(adjLink[0], distance + adjLink[1])) result = [0] * V for i in range(V): result[i] = map[i].distance return result def main(): adj = [[] for _ in range(6)] V = 6 E = 5 u = [0, 0, 1, 2, 4] v = [3, 5, 4, 5, 5] w = [9, 4, 4, 10, 3] for i in range(E): edge = [v[i], w[i]] adj[u[i]].append(edge) edge2 = [u[i], w[i]] adj[v[i]].append(edge2) S = 1 result = dijkstra(V, adj, S) print(result) if __name__ == '__main__': main() # This code is contributed by ragul21> C# // C# Code: using System; using System.Collections.Generic; public class Graph { // No. of vertices private int V; // adjacency list private List>[] 形容詞; // コンストラクター public Graph(int v) { V = v; adj = 新しいリスト>[ v ]; for (int i = 0; i< v; ++i) adj[i] = new List>(); } // グラフにエッジを追加する関数 public void addEdge(int u, int v, int w) { adj[u].Add(Tuple.Create(v, w)); adj[v].Add(Tuple.Create(u, w)); } // s からの最短パスを出力 public void ShortestPath(int s) { // 前処理中の頂点を格納する優先キューを作成 // var pq = 新しい PriorityQueue>(); // 距離のベクトルを作成し、 // すべての距離を無限 (INF) として初期化します var dist = new int[V]; for (int i = 0; i< V; i++) dist[i] = int.MaxValue; // Insert source itself in priority queue and // initialize its distance as 0. pq.Enqueue(Tuple.Create(0, s)); dist[s] = 0; /* Looping till priority queue becomes empty (or all distances are not finalized) */ while (pq.Count != 0) { // The first vertex in pair is the minimum // distance vertex, extract it from priority // queue. vertex label is stored in second of // pair (it has to be done this way to keep the // vertices sorted distance (distance must be // first item in pair) var u = pq.Dequeue().Item2; // 'i' is used to get all adjacent vertices of a // vertex foreach(var i in adj[u]) { // Get vertex label and weight of current // adjacent of u. int v = i.Item1; int weight = i.Item2; // If there is shorted path to v through u. if (dist[v]>dist[u] + Weight) { // v の距離を更新 dist[v] = dist[u] + Weight; pq.Enqueue(Tuple.Create(dist[v], v)); } } } // dist[] に保存されている最短距離を出力します Console.WriteLine('ソースからの頂点距離'); for (int i = 0; i< V; ++i) Console.WriteLine('{0} {1}', i, dist[i]); } } public class PriorityQueue{ プライベート読み取り専用リスト_データ; プライベート読み取り専用の比較_比較した; public PriorityQueue(): this(比較.Default) { } public PriorityQueue(IComparer)比較): this(比較.比較) { } public PriorityQueue(比較比較) { _data = 新しいリスト(); _compare = 比較; public void Enqueue(T item) { _data.Add(item); var childIndex = _data.Count - 1; while (childIndex> 0) { varparentIndex = (childIndex - 1) / 2; if (_compare(_data[childIndex], _data[parentIndex])>= 0) ブレーク; T tmp = _data[childIndex]; _data[子インデックス] = _データ[親インデックス]; _data[親インデックス] = tmp; childIndex = 親インデックス; } } public T Dequeue() { // pq が空ではないと仮定します。コードを呼び出すまで var lastElement = _data.Count - 1; varfrontItem = _data[0]; _data[0] = _data[lastElement]; _data.RemoveAt(lastElement); --lastElement; varparentIndex = 0; while (true) { var childIndex =parentIndex * 2 + 1; if (childIndex> lastElement) ブレーク; // ツリーの終わり var rightChild = childIndex + 1; if (右子<= lastElement && _compare(_data[rightChild], _data[childIndex]) < 0) childIndex = rightChild; if (_compare(_data[parentIndex], _data[childIndex]) <= 0) break; // Correct position T tmp = _data[parentIndex]; _data[parentIndex] = _data[childIndex]; _data[childIndex] = tmp; parentIndex = childIndex; } return frontItem; } public T Peek() { T frontItem = _data[0]; return frontItem; } public int Count { get { return _data.Count; } } } class Program { // Driver program to test methods of graph class static void Main(string[] args) { // create the graph given in above figure int V = 7; Graph g = new Graph(V); // making above shown graph g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); } }> JavaScript class PriorityQueue { constructor() { this.queue = []; } enqueue(element, priority) { this.queue.push({ element, priority }); this.queue.sort((a, b) =>a.優先度 - b.優先度); dequeue() { if (this.isEmpty()) { null を返します。 this.queue.shift().element を返します。 isEmpty() { return this.queue.length === 0; } } class Graph {constructor(V) { this.V = V; this.adj = 新しい配列(V); for (i = 0 とする; i< V; i++) { this.adj[i] = []; } } addEdge(u, v, w) { this.adj[u].push({ v, w }); this.adj[v].push({ v: u, w }); } shortestPath(src) { const pq = new PriorityQueue(); const dist = new Array(this.V).fill(Infinity); const visited = new Array(this.V).fill(false); pq.enqueue(src, 0); dist[src] = 0; while (!pq.isEmpty()) { const u = pq.dequeue(); if (visited[u]) continue; visited[u] = true; for (const { v, w } of this.adj[u]) { if (!visited[v] && dist[u] + w < dist[v]) { dist[v] = dist[u] + w; pq.enqueue(v, dist[v]); } } } console.log('Vertex Distance from Source'); for (let i = 0; i < this.V; i++) { console.log(`${i} ${dist[i] === Infinity ? 'Infinity' : dist[i]}`); } } } function main() { const V = 7; const g = new Graph(V); g.addEdge(0, 1, 2); g.addEdge(0, 2, 6); g.addEdge(1, 3, 5); g.addEdge(2, 3, 8); g.addEdge(3, 4, 10); g.addEdge(3, 5, 15); g.addEdge(4, 6, 2); g.addEdge(5, 6, 6); g.shortestPath(0); } main();> 最終的な答え:
Python __dict__

出力
ダイクストラアルゴリズムの複雑性解析 :
- 時間計算量: O((V + E) log V) 、 ここで、V は頂点の数、E はエッジの数です。
- 補助スペース: O(V)。ここで、V はグラフ内の頂点の数、E はエッジの数です。
2.ダイクストラアルゴリズムの配列ベースの実装 (単純なアプローチ):
ダイクストラのアルゴリズムは、優先キューを使用せずに配列を使用して実装することもできます。この実装は簡単ですが、特に大きなグラフでは効率が低下する可能性があります。
アルゴリズムは次のように進行します。
- ソースから各ノードまでの距離を格納する配列を初期化します。
- すべてのノードを未訪問としてマークします。
- ソース ノードまでの距離を 0 に設定し、他のすべてのノードについては無限大に設定します。
- すべてのノードにアクセスするまで繰り返します。
- 既知の最小距離を持つ未訪問のノードを見つけます。
- 現在のノードについて、未訪問の隣接ノードの距離を更新します。
- 現在のノードを訪問済みとしてマークします。
複雑さの分析:
- 時間計算量: 最悪の場合は O(V^2) (V は頂点の数)。これは、いくつかの最適化を行うことで O(V^2) まで改善できます。
- 補助スペース: O(V)。ここで、V はグラフ内の頂点の数、E はエッジの数です。
ダイクストラのアルゴリズムとベルマンフォードのアルゴリズム
ダイクストラのアルゴリズムと ベルマン・フォードアルゴリズム どちらも重み付きグラフ内の最短経路を見つけるために使用されますが、いくつかの重要な違いがあります。ダイクストラのアルゴリズムとベルマンフォード アルゴリズムの主な違いは次のとおりです。
| 特徴: | ディクストラの | ベルマン・フォード |
|---|---|---|
| 最適化 | 非負のエッジ重みを持つグラフ内の単一のソース ノードと他のすべてのノードの間の最短パスを見つけるために最適化されています。 | Bellman-Ford アルゴリズムは、負のエッジの重みを持つグラフ内の単一のソース ノードと他のすべてのノードの間の最短パスを見つけるために最適化されています。 |
| リラクゼーション | ダイクストラのアルゴリズムは、距離が最小のノードを選択し、その近傍ノードを更新する貪欲なアプローチを使用します。 | Bellman-Ford アルゴリズムは、各反復ですべてのエッジを緩和し、そのノードへのすべての可能なパスを考慮して各ノードの距離を更新します。 |
| 時間計算量 | ダイクストラのアルゴリズムの時間計算量は、密グラフの場合は O(V^2)、疎グラフの場合は O(E log V) です。ここで、V は頂点の数、E はグラフ内のエッジの数です。 | Bellman-Ford アルゴリズムの時間計算量は O(VE) です。ここで、V はグラフ内の頂点の数、E はエッジの数です。 |
| 負の重み | ダイクストラのアルゴリズムは、すべてのエッジの重みが負ではないことを前提としているため、負のエッジの重みを持つグラフでは機能しません。 | Bellman-Ford アルゴリズムは、負のエッジの重みを処理でき、グラフ内の負の重みサイクルを検出できます。 |
ダイクストラのアルゴリズムとフロイド・ウォーシャルのアルゴリズム
ダイクストラのアルゴリズムと フロイド・ウォーシャルアルゴリズム どちらも重み付きグラフ内の最短経路を見つけるために使用されますが、いくつかの重要な違いがあります。ダイクストラのアルゴリズムとフロイド・ウォーシャルのアルゴリズムの主な違いは次のとおりです。
| 特徴: | ディクストラの | フロイド・ウォーシャルアルゴリズム |
|---|---|---|
| 最適化 | 非負のエッジ重みを持つグラフ内の単一のソース ノードと他のすべてのノードの間の最短パスを見つけるために最適化されています。 | Floyd-Warshall アルゴリズムは、グラフ内のノードのすべてのペア間の最短パスを見つけるために最適化されています。 |
| 技術 | ダイクストラのアルゴリズムは、貪欲なアプローチを使用し、ソース ノードからグラフ内の他のすべてのノードまでの最短パスを計算する、単一ソースの最短パス アルゴリズムです。 | 一方、Floyd-Warshall アルゴリズムは、動的プログラミングを使用してグラフ内のノードのすべてのペア間の最短パスを計算する全ペア最短パス アルゴリズムです。 |
| 時間計算量 | ダイクストラのアルゴリズムの時間計算量は、密グラフの場合は O(V^2)、疎グラフの場合は O(E log V) です。ここで、V は頂点の数、E はグラフ内のエッジの数です。 | 一方、Floyd-Warshall アルゴリズムは、動的プログラミングを使用してグラフ内のノードのすべてのペア間の最短パスを計算する全ペア最短パス アルゴリズムです。 |
| 負の重み | ダイクストラのアルゴリズムは、すべてのエッジの重みが負ではないことを前提としているため、負のエッジの重みを持つグラフでは機能しません。 | 一方、Floyd-Warshall アルゴリズムは、動的プログラミングを使用してグラフ内のノードのすべてのペア間の最短パスを計算する全ペア最短パス アルゴリズムです。 |
ダイクストラのアルゴリズムと A* アルゴリズム
ダイクストラのアルゴリズムと A* アルゴリズム どちらも重み付きグラフ内の最短経路を見つけるために使用されますが、いくつかの重要な違いがあります。ダイクストラのアルゴリズムと A* アルゴリズムの主な違いは次のとおりです。
| 特徴: | A* アルゴリズム | |
|---|---|---|
| 検索テクニック | 非負のエッジ重みを持つグラフ内の単一のソース ノードと他のすべてのノードの間の最短パスを見つけるために最適化されています。 | A* アルゴリズムは、ヒューリスティック関数を使用して目標ノードに向かって検索をガイドする、情報に基づいた検索アルゴリズムです。 |
| ヒューリスティック関数 | ダイクストラのアルゴリズムはヒューリスティック関数を使用せず、グラフ内のすべてのノードを考慮します。 | A* アルゴリズムは、現在のノードからゴール ノードまでの距離を推定するヒューリスティック関数を使用します。このヒューリスティック関数は許容可能です。つまり、ゴール ノードまでの実際の距離を過大評価することはありません。 |
| 時間計算量 | ダイクストラのアルゴリズムの時間計算量は、密グラフの場合は O(V^2)、疎グラフの場合は O(E log V) です。ここで、V は頂点の数、E はグラフ内のエッジの数です。 | A* アルゴリズムの時間計算量は、ヒューリスティック関数の品質に依存します。 |
| 応用 | ダイクストラのアルゴリズムは、ルーティング アルゴリズム、GPS ナビゲーション システム、ネットワーク分析などの多くのアプリケーションで使用されています。 | 。 A* アルゴリズムは、ビデオ ゲーム、ロボット工学、計画アルゴリズムなどの経路探索やグラフ探索問題でよく使用されます。 |
ダイクストラのアルゴリズムに関する練習問題:
- ダイクストラの最短経路アルゴリズム |貪欲なアルゴ-7
- 隣接リスト表現のためのダイクストラのアルゴリズム |貪欲なアルゴ-8
- ダイクストラのアルゴリズム – 優先キューと配列の実装
- STL のセットを使用したダイクストラの最短経路アルゴリズム
- C++ で STL を使用したダイクストラの最短パス アルゴリズム
- STLのpriority_queueを利用したダイクストラの最短パスアルゴリズム
- C++ の行列を使用したダイクストラの最短経路アルゴリズム
- DAG 内の単一ソース最短パスのためのダイクストラのアルゴリズム
- フィボナッチヒープを使用したダイクストラのアルゴリズム
- 負の重みをもつ有向グラフ用のダイクストラの最短経路アルゴリズム
- ダイクストラの最短パス アルゴリズムでのパスの印刷
- Java の優先キューを使用したダイクストラの最短パス アルゴリズム




