私はどこでもPrimsアルゴリズムの時間の複雑さをO((V + E)log V E log V)==として見つけました。しかし、アルゴリズムを見ることができるように:
時間の複雑さはO(V(log V + E log V))のようです。しかし、その時間の複雑さがO((V + E)log V)である場合。次に、ネストは次のようにする必要があります。
しかし、上記の入れ子は間違っているようです。
_MST-PRIM(G, w, r)
1 for each u ∈ G.V
2 u.key ← ∞
3 u.π ← NIL
4 r.key ← 0
5 Q ← G.V
6 while Q ≠ Ø
7 u ← EXTRACT-MIN(Q)
8 for each v ∈ G.Adjacent[u]
9 if v ∈ Q and w(u, v) < v.key
10 v.π ← u
11 v.key ← w(u, v)
_
バイナリヒープの使用
EXTRACT-MIN(Q)
の1回の呼び出しに必要な時間の複雑さは、最小優先度キューを使用したO(log V)
です。 6行目のwhileループは合計V回実行しています。したがって、EXTRACT-MIN(Q)
はV
回呼び出されます。したがって、EXTRACT-MIN(Q)
の複雑さはO(V logV)
です。
無向グラフの各隣接リストの長さは_2E
_であるため、8行目のfor
ループは合計_2E
_回実行しています。 11行目を実行するのに必要な時間は、最小ヒープで_DECREASE_KEY
_演算を使用することによるO(log v)
です。 11行目も合計_2E
_回実行します。したがって、行11の実行に必要な合計時間はO(2E logV) = O(E logV)
です。
1行目のfor
ループはV
回実行されます。手順を使用して1〜5行目を実行するには、複雑なO(V)
が必要になります。
_MST-PRIM
_の合計時間の複雑さは、ステップ1〜3を実行するために必要な合計時間O(VlogV + (E logV + V) = O(E logV)
の合計です。
フィボナッチヒープの使用
O(1)
の償却時間が必要です。 11行目では、合計_2E
_回実行されます。したがって、総時間の複雑さはO(E)
です。したがって、_MST-PRIM
_の合計時間の複雑さは、O(V logV + E + V)=O(E + V logV)
の合計複雑度に対してステップ1〜3を実行した合計です。
Primのアルゴリズムの時間の複雑さはO(VlogV + ElogV)です。 VlogV
がどのようになってきたのか理解しているようですので、スキップしてみましょう。では、ElogV
はどこから来たのでしょうか?まず、プリムのアルゴリズムのソースコードを見てみましょう。
_ | MST-PRIM(Graph, weights, r)
1 | for each u ∈ Graph.V
2 | u.key ← ∞
3 | u.π ← NIL
4 | r.key ← 0
5 | Q ← Graph.V
6 | while Q ≠ Ø
7 | u ← EXTRACT-MIN(Q)
8 | for each v ∈ Graph.Adj[u]
9 | if v ∈ Q and weights(u, v) < v.key
10| v.π ← u
11| v.key ← weights(u, v)
_
8〜11行目はQ
のすべての要素に対して実行され、V
にはQ
要素があることを知っています(すべての頂点のセットを表します)。行8のループは、現在抽出されている頂点のすべての近傍を反復しています。次の抽出された頂点とその後の頂点についても同じことを行います。 Djistkraのアルゴリズムは頂点を繰り返しません(貪欲で最適なアルゴリズムであるため)。結局、接続されている各頂点を調べ、隣接するすべての頂点を探索します。つまり、このループは、ある時点でグラフのすべてのエッジを2回通過することになります(_2E
_)。
なぜ二度?ある時点で、以前に探索したEdgeに別の方向から戻り、実際に確認するまで除外できないためです。幸い、その定数_2
_は、時間の複雑さの分析中に削除されるため、ループは実際にE
の量の作業を実行しています。
なぜそれは_V*V
_ではなかったのですか?各頂点とその近傍をチェックする必要があると考えれば、この用語に到達する可能性があり、最悪の場合、近傍の数はV
に近づきます。確かに、密なグラフでは_V*V = E
_。しかし、これらの2つのループの動作のより正確な説明は「すべてのエッジを2回通過する」ことなので、代わりにE
を参照します。グラフの疎性とこの用語の時間の複雑さを関連付けるのは読者次第です。
4つの頂点を持つ小さなサンプルグラフを見てみましょう。
_ 1--2
|\ |
| \|
3--4
_
Q
が1、2、3、4の順にノードを提供すると仮定します。
反復の合計は10で、これはエッジの数の2倍です(_2*5
_)。
最小値の抽出と更新された最小エッジの追跡(通常はフィボナッチヒープで行われ、その結果log(V)
時間の複雑性が生じます)はループの反復内で発生します-正確なメカニズムには、内部ループ内で十分な回数発生する必要がある両方のループの時間の複雑さによって制御されていること。したがって、アルゴリズムのこのフェーズの完全な時間の複雑さはO(2*E*log(V))
です。定数を削除すると、O(E*log(V))
が生成されます。
アルゴリズムの合計時間の複雑さがO(VlogV + ElogV)
であるとすると、O((V+E)logV)
に簡略化できます。密なグラフ_E > V
_では、O(ElogV)
と結論付けることができます。
あなたの考えは正しいようです。複雑さをV(lg(v) + E(lg(v)))
と考えてみましょう。内側のforループでは、実際にはEdgeではなくすべての頂点を通過していることに注意してください。V(lg(v) + V(lg(v)))
に少し変更して、V(lg(v)) + V*V(lg(v))
しかし、最悪のケースの分析(密なグラフ)の場合、V * Vはエッジの数にほぼ等しく、E V(lg(v)) + E(lg(v))
(V+E((lg(v))
ですが、V << E
なので、E(lg(v))
実際には、時間の複雑性はv.E lg Vである必要がありますが、漸近分析の場合は正しいです。しかし、コーメンでは、償却分析を行っているため、(Elogv)