ダイクストラのアルゴリズムとプリムのアルゴリズムの正確な違いは何ですか? Prim'sがMSTを与えることは知っていますが、Dijkstraによって生成されたツリーもMSTになります。次に、正確な違いは何ですか?
Primのアルゴリズムは、グラフの 最小スパニングツリー を構築します。これは、グラフ内のすべてのノードを接続し、すべてのノードを接続するすべてのツリーの中で最小の総コストを持つツリーです。ただし、MSTの2つのノード間のパスの長さは、元のグラフの2つのノード間の最短パスではない場合があります。 MSTは、たとえば、グラフ内のノードを物理的に接続して、最小の合計コストでノードに電力を供給したい場合に役立ちます。気になるのは接続されているという事実だけなので、2つのノード間のパスの長さが最適でなくてもかまいません。
ダイクストラのアルゴリズムは、ソースノードから始まる 最短パスツリー を構築します。最短パスツリーは、グラフ内のすべてのノードを接続してソースノードに戻すツリーであり、ソースノードからグラフ内の他のノードまでのパスの長さを最小化するプロパティがあります。これは、たとえば、誰もが主要な重要なランドマークに到達できるように可能な限り効率的な道路ネットワークを構築したい場合に便利です。ただし、最短パスツリーが最小スパニングツリーであるとは限りません。そのようなツリーを構築するコストは、MSTのコストよりもはるかに大きくなる可能性があります。
もう1つの重要な違いは、アルゴリズムが機能するグラフの種類に関するものです。プリムのアルゴリズムは、無向グラフでのみ機能します。MSTの概念は、グラフは本質的に無向であると想定しているためです。 (有向グラフには「最小全域木」と呼ばれるものがありますが、それらを見つけるアルゴリズムははるかに複雑です)。 Dijkstraのアルゴリズムは、最短経路ツリーを実際に向けることができるため、有向グラフでは正常に機能します。さらに、Dijkstraのアルゴリズム 負のEdgeの重みを含むグラフで必ずしも正しい解が得られるとは限りません 、Primのアルゴリズムはこれを処理できます。
お役に立てれば!
ダイクストラのアルゴリズムはMSTを作成せず、最短経路を見つけます。
このグラフを考えてください
5 5
s *-----*-----* t
\ /
-------
9
最短パスは9ですが、MSTは10の異なる「パス」です。
プリムとダイクストラのアルゴリズムは、「リラックス機能」を除いてほとんど同じです。
プリム内:
MST-PRIM (G, w, r) {
for each key ∈ G.V
u.key = ∞
u.parent = NIL
r.key = 0
Q = G.V
while (Q ≠ ø)
u = Extract-Min(Q)
for each v ∈ G.Adj[u]
if (v ∈ Q) and w(u,v) < v.key
v.parent = u
v.key = w(u,v) <== relax function, Pay attention here
}
ダイクストラで:
Dijkstra (G, w, r) {
for each key ∈ G.V
u.key = ∞
u.parent = NIL
r.key = 0
Q = G.V
while (Q ≠ ø)
u = Extract-Min(Q)
for each v ∈ G.Adj[u]
if (v ∈ Q) and w(u,v) < v.key
v.parent = u
v.key = w(u,v) + u.key <== relax function, Pay attention here
}
唯一の違いは、コードの最後の行であるリラックス機能です。最小スパニングツリーを検索するプリムは、すべての頂点をカバーする合計エッジの最小値のみを考慮します。次のようになります。v.key = w(u、v)最小パス長を検索するダイクストラ。エッジの累積を考慮します。したがって、次のようになります:v.key = w(u、v)+ u.key
ダイクストラは、開始ノードと他のすべてのノードとの間の最短経路を見つけます。したがって、見返りに、開始ノードから最小距離ツリーを取得します。つまり、できるだけ効率的に他のすべてのノードに到達できます。
プリムアルゴリズムは、指定されたグラフ、つまり、すべてのコストの合計が可能な限り最小であるすべてのノードを接続するツリーのMSTを取得します。
現実的な例でストーリーを短くするには:
DijkstraのAlgorithm's ウィキペディアの記事から直接:
ダイクストラのアルゴリズムの基礎となるプロセスは、プリムのアルゴリズムで使用される欲張りプロセスに似ています。 Primの目的は、グラフ内のすべてのノードを接続する最小スパニングツリーを見つけることです。ダイクストラは、2つのノードのみに関係しています。プリムは、開始ノードからのパスの総重量を評価するのではなく、個々のパスのみを評価します。
基本的なアルゴリズムの主な違いは、異なるエッジ選択基準にあります。一般的に、どちらも次のノードの選択に優先度キューを使用しますが、現在の処理ノードの隣接ノードを選択するための異なる基準があります:プリムのアルゴリズムでは、次の隣接ノードもキューに保持する必要がありますが、ダイクストラのアルゴリズムはそうではありません:
def dijkstra(g, s):
q <- make_priority_queue(VERTEX.distance)
for each vertex v in g.vertex:
v.distance <- infinite
v.predecessor ~> nil
q.add(v)
s.distance <- 0
while not q.is_empty:
u <- q.extract_min()
for each adjacent vertex v of u:
...
def prim(g, s):
q <- make_priority_queue(VERTEX.distance)
for each vertex v in g.vertex:
v.distance <- infinite
v.predecessor ~> nil
q.add(v)
s.distance <- 0
while not q.is_empty:
u <- q.extract_min()
for each adjacent vertex v of u:
if v in q and weight(u, v) < v.distance:// <-------selection--------
...
vertex.distanceの計算は、2番目の異なる点です。
最初の違いは、ダイクストラのアルゴリズムがクラスカルおよびプリムとは異なる問題を解決することです。 Dijkstraは最短パス問題を(指定されたノードから)解決しますが、KruskalとPrimは最小コストのスパニングツリーを見つけます。以下は、このページで書いた説明の修正版です。グラフアルゴリズム。
どのグラフでも、スパニングツリーは、頂点のすべてのペア間に正確に1つのパスを提供するのに十分なエッジのコレクションです。この制限は、選択されたエッジによって形成される回路がないことを意味します。
最小コストのスパニングツリーとは、可能な最小の合計重みを持つものです(重みはコストまたは距離を表します)。このようなツリーは複数ある場合がありますが、PrimとKruskalはどちらもそのうちの1つを見つけることが保証されています。
指定された頂点(Xなど)の場合、最短パスツリーはスパニングツリーであり、Xから他の頂点へのパスはできるだけ短くなります(つまり、可能な最小の重みを持ちます)。
PrimとDijkstraは、開始頂点からツリーを「成長」させます。つまり、「ローカル」フォーカスを持っています。各ステップで、以前に選択した頂点に隣接するエッジのみを考慮し、ニーズを満たす最も安価なオプションを選択します。一方、クラスカルは「グローバル」アルゴリズムです。つまり、各エッジはグラフ全体から(欲張りに)選択されます。 (実際、ダイクストラは、以下に示すように、グローバルな側面を持っていると見なされる場合があります。)
最小コストのスパニングツリーを見つけるには:
クラスカル(グローバルアプローチ):各ステップで、スパニングツリーを作成するという目標に違反しない、最も安価で利用可能なエッジを選択します。プリム(ローカルアプローチ):開始頂点を選択します。連続する各ステップで、スパニングツリー作成の目標に違反しない、以前に選択した頂点にアタッチされている最も安価なエッジを選択します。最短パススパニングツリーを見つけるには:
ダイクストラ:各ステップで、以前に選択した頂点(ローカルアスペクト)にアタッチされたエッジを選択します。これにより、開始頂点(グローバルアスペクト)からの合計距離が可能な限り小さくなり、スパニングツリーの作成の目標に違反しません。 。
最小コストツリーと最短パスツリーは、それらを解決するPrimおよびDijkstraアルゴリズムと同様に、簡単に混同されます。両方のアルゴリズムは開始頂点から「成長」し、各ステップで、ツリー内の頂点Yを頂点Zに接続するEdgeを選択します。ただし、Primはそのような最も安価なEdgeを選択しますが、DijkstraはXからZへの最短パスをもたらすEdgeを選択します。
これらのアルゴリズムとそれらが生成するツリーの違いを理解するには、簡単な図が役立ちます。下のグラフでは、頂点Aから始まり、PrimとDijkstraの両方がEdge ABを選択してからEdge BDを追加することから始まります。 2つのアルゴリズムの分岐点は次のとおりです。プリムはエッジDCを追加してツリーを完成させますが、ダイクストラはACまたはBCを追加します。これは、パスA-CおよびA-B-C(両方とも合計距離30)がパスA-B-D-C(合計距離31)よりも短いためです。
ダイクストラアルゴリズムは、最短パスを見つけるためにのみ使用されます。
最小スパニングツリー(PrimまたはKruskalのアルゴリズム)では、最小Edge値で最小egdesを取得します。
例:-uが多数のワイヤを必要とするような巨大なネットワークを作成したくない場合、これらのワイヤのカウントが最小スパニングツリー(プリムまたはクラスカルのアルゴリズム)(つまり、最小コストで巨大な有線ネットワーク接続を作成するために最小数のワイヤを提供します)。
一方、"Dijkstras algorithm"は、ノードを相互に接続しながら2つのノード間の最短パスを取得するために使用されます。
@templatetypedefは、MSTと最短パスの違いをカバーしています。 another So answer のアルゴリズムの違いについて説明しました。入力としてもう1つのパラメーターを使用する同じ汎用アルゴリズムを使用して、両方を実装できることを示すことにより、関数f(u,v)
PrimとDijkstraのアルゴリズムの違いは、使用するf(u,v)
だけです。
コードレベルでのもう1つの違いは、APIです。
ソース頂点、s、つまりPrim.new(s)
;でPrimを初期化します。 sは任意の頂点であり、sに関係なく、最終結果は最小スパニングツリー(MST)のエッジと同じです。 MSTエッジを取得するには、edges()
メソッドを呼び出します。
Dijkstraをソース頂点sで初期化します。つまり、Dijkstra.new(s)
で、他のすべての頂点への最短パス/距離を取得します。最終結果は、sから他のすべての頂点までの最短経路/距離です。 sによって異なります。 sから任意の頂点vまでの最短経路/距離を取得するには、それぞれdistanceTo(v)
メソッドとpathTo(v)
メソッドを呼び出します。