コンピュータサイエンスにおいて、シャドウヒープとは、償却的な意味での効率的なヒープマージをサポートするマージ可能なヒープ データ構造です。より具体的には、シャドウヒープはシャドウマージアルゴリズムを利用して、 1 ≤ f( n ) ≤ log log nの任意の値に対して、挿入をO (f(n ) ) 償却時間、削除をO ((log n log log n )/f( n )) 償却時間で実現します。[1]
この記事では、 AとBが | A | ≤ | B |のバイナリ ヒープであると想定します。
シャドウマージ
シャドウマージは、 2つのバイナリヒープが配列として実装されている場合、それらを効率的にマージするアルゴリズムです。具体的には、2つのヒープとにおけるシャドウマージの実行時間は
です


アルゴリズム
2つのバイナリ最小ヒープとをマージします。アルゴリズムは次のとおりです


- 配列の末尾に配列を連結して配列を取得します。



- 内の のシャドウ、つまりヒープ プロパティを破壊する内の最後のノードの祖先を識別します。




- から影の次の 2 つの部分を特定します。

- パス: 任意の 深さで最大 2 個存在する影内のノードのセット。


- サブツリー: 影の残り部分。

- 影から最小のノードを抽出し、配列に並べ替えます。


- 次のように変換します。

- の場合、ソートされた配列の最小の要素から始めて、 の各要素を の最小の要素で置き換えて に順番に挿入します。




- の場合、から最小の要素を抽出してソートし、このソートされたリストを とマージします。




- の要素をの元の位置に置き換えます。


- を山盛りにします。

実行時間
ここでも、 はパスを表し、 は連結ヒープ のサブツリーを表します。 のノード数はの深さの最大2倍、つまり です。さらに、の深さにおけるノード数は、の深さにおけるノード数の3/4以下であるため、サブツリーのサイズは です。 の各レベルには最大2つのノードがあるため、シャドウの最小要素をソート済み配列に読み込むには時間がかかります。














の場合、上記のステップ5のようにとを結合するのに 時間がかかります。それ以外の場合、このステップにかかる時間は です。最後に、サブツリーのヒープ作成には 時間がかかります。これは、 のシャドウマージにかかる合計実行時間になります。








構造
シャドウヒープは、閾値関数と、最初のエントリでは通常の配列実装のバイナリヒープ特性が維持され、他のエントリではヒープ特性が必ずしも維持されない配列で構成されます。したがって、シャドウヒープは本質的に配列に隣接するバイナリヒープです。シャドウヒープに要素を追加するには、配列に配置します。指定された閾値に従って配列が大きくなりすぎた場合は、まずフロイドのヒープ構築アルゴリズム[2]を使用してヒープを構築し、次にシャドウマージを使用してこのヒープをとマージします。最後に、シャドウヒープのマージは、上記の挿入手順を使用して、1つのヒープを別のヒープに順番に挿入することによって行われます







解析
シャドウヒープが与えられ、閾値関数は上記と同じです。閾値関数は、 の変化が の変化よりも大きくならないようなものと仮定します。償却解析のポテンシャル法を用いて、マージ可能なヒープ操作の望ましい実行時間の上界を導出します。ヒープの
ポテンシャルは次のように選択されます





このポテンシャルを使用すると、必要な償却実行時間を取得できます。
create( H ) : 新しい空のシャドウヒープを初期化する
- ここでは、潜在的価値は変わらないので、創造の償却コストは、実際のコストになります。


insert( x , H ) :シャドウヒープに挿入する
- 2つのケースがあります:
- マージが採用された場合、ポテンシャル関数の低下は と のマージの実際のコストとまったく同じなので、償却コストは になります。



- 合併が行われない場合、償却原価は

- 閾値関数の選択により、挿入の償却コストは次のようになります。

delete_min( H ) : 最小優先度の要素を削除します。
- 最小値を見つけて削除するには、実際の時間 かかります。さらに、 の値が減少した場合にのみ、この削除後にポテンシャル関数が増加します。 を選択することで、この操作の償却コストは実際のコストと同じになります。



単純なバイナリヒープマージアルゴリズムは、2つのヒープを単純に連結し、その結果得られた配列からフロイドのヒープ構築アルゴリズムを用いてヒープを作成することで、 2つのヒープをでマージします。あるいは、 の各要素をに順番に挿入することで、 の時間を要してヒープをマージすることもできます。






サックとストロトホッテは、バイナリヒープを時間内にマージするアルゴリズムを提案した。[3]彼らのアルゴリズムは、およそ の場合に、上記の2番目の単純な解決策よりも効率的であることが知られている。シャドウマージは、最悪の場合でも、彼らのアルゴリズムよりも漸近的に優れたパフォーマンスを発揮する。


より高速なマージ時間をサポートするヒープは他にもいくつかあります。例えば、フィボナッチヒープは時間内にマージできます。バイナリヒープはマージに時間がかかるため、[4]シャドウマージは依然として効率的です。


参考文献
- ^ Kuszmaul, Christopher L. (2000). バイナリヒープとバイナリツリーの効率的なマージおよび挿入操作(PDF) (技術レポート). NASA Advanced Supercomputing Division. 00-003
- ^ Suchenek, Marek A. (2012)、「Floydのヒープ構築プログラムの初歩的かつ正確な最悪ケース分析」、Fundamenta Informaticae、120 (1)、IOS Press: 75– 92、doi :10.3233/FI-2012-751
- ^ Sack, Jörg-R.; Strothotte, Thomas (1985)、「ヒープのマージのためのアルゴリズム」、Acta Informatica、22 (2)、Springer-Verlag: 171– 186、doi :10.1007/BF00264229、S2CID 6427624。
- ^ コーメン、トーマス・H.、レイサーソン、チャールズ・E.、リベスト、ロナルド・L. (1990). 『アルゴリズム入門(第1版)』MITプレス、マグロウヒル. ISBN 0-262-03141-8。