web-dev-qa-db-ja.com

プリムアルゴリズムの時間の複雑さ?

私はどこでもPrimsアルゴリズムの時間の複雑さをO((V + E)log V E log V)==として見つけました。しかし、アルゴリズムを見ることができるように:

時間の複雑さはO(V(log V + E log V))のようです。しかし、その時間の複雑さがO((V + E)log V)である場合。次に、ネストは次のようにする必要があります。

しかし、上記の入れ子は間違っているようです。

9
Sonali
_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)
_

バイナリヒープの使用

  1. EXTRACT-MIN(Q)の1回の呼び出しに必要な時間の複雑さは、最小優先度キューを使用したO(log V)です。 6行目のwhileループは合計V回実行しています。したがって、EXTRACT-MIN(Q)V回呼び出されます。したがって、EXTRACT-MIN(Q)の複雑さはO(V logV)です。

  2. 無向グラフの各隣接リストの長さは_2E_であるため、8行目のforループは合計_2E_回実行しています。 11行目を実行するのに必要な時間は、最小ヒープで_DECREASE_KEY_演算を使用することによるO(log v)です。 11行目も合計_2E_回実行します。したがって、行11の実行に必要な合計時間はO(2E logV) = O(E logV)です。

  3. 1行目のforループはV回実行されます。手順を使用して1〜5行目を実行するには、複雑なO(V)が必要になります。

_MST-PRIM_の合計時間の複雑さは、ステップ1〜3を実行するために必要な合計時間O(VlogV + (E logV + V) = O(E logV)の合計です。

フィボナッチヒープの使用

  1. 同上。
  2. 11行目を実行するには、O(1)の償却時間が必要です。 11行目では、合計_2E_回実行されます。したがって、総時間の複雑さはO(E)です。
  3. 同上

したがって、_MST-PRIM_の合計時間の複雑さは、O(V logV + E + V)=O(E + V logV)の合計複雑度に対してステップ1〜3を実行した合計です。

28
tanmoy

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の順にノードを提供すると仮定します。

  • 外側のループの最初の反復では、内側のループが3回実行されます(2、3、および4の場合)。
  • 外側のループの2回目の反復では、内側のループが2回実行されます(1と4の場合)。
  • 外側のループの3番目の反復では、内側のループが2回実行されます(1と4の場合)。
  • 外側のループの最後の反復では、内側のループが3回実行されます(1、2、3の場合)。

反復の合計は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)と結論付けることができます。

3
Anshu Shahi

あなたの考えは正しいようです。複雑さを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))

3
user3473400

実際には、時間の複雑性はv.E lg Vである必要がありますが、漸近分析の場合は正しいです。しかし、コーメンでは、償却分析を行っているため、(Elogv)

1
Rakhi