a、bの2つの並べ替えられた配列[〜#〜] t [〜#〜]サイズnおよびm。 2つの配列を新しい配列(最大サイズn + m)にマージするアルゴリズムを探しています。
安価な比較操作がある場合、これは非常に簡単です。 1つまたは両方の配列が完全にトラバースされるまで、最初の要素が最も低い配列から取り出し、残りの要素を追加します。このようなもの https://stackoverflow.com/questions/5958169/how-to-merge-two-sorted-arrays-into-a-sorted-array
ただし、2つの要素を比較すると、ソース配列からターゲット配列に要素をコピーするよりもはるかにコストがかかると状況が変わります。たとえば、大きな任意精度の整数または文字列の配列があり、比較に非常にコストがかかる場合があります。 配列の作成と要素のコピーは無料であり、コストがかかるのは要素の比較だけであると仮定します。
この場合、2つの配列を最小数の要素比較でマージします。次に、単純なマージアルゴリズムよりもはるかに優れた例を示します。
a = [1,2,3,4, ... 1000]
b = [1001,1002,1003,1004, ... 2000]
または
a = [1,2,3,4, ... 1000]
b = [0,100,200, ... 1000]
単純なマージアルゴリズムが最適になるケースがいくつかあります。
a = [1,3,5,7,9,....,999]
b = [2,4,6,8,10,....,1000]
したがって、配列がインターリーブされている場合、または少なくとも大幅に悪化していない場合、アルゴリズムは理想的には優雅に低下し、最大n + m-1の比較を実行する必要があります。
サイズの違いが大きいリストでかなりうまくいくはずの1つは、バイナリ検索を使用して、小さい配列の要素を大きい配列に挿入することです。ただし、両方のリストのサイズが同じでインターリーブされている場合は、正常に機能が低下することはありません。
要素で使用できるのは(合計)順序付け関数だけなので、比較をより安価にするスキームは不可能です。
何か案は?
私は Scalaのこのビット を考え出しました。比較の数に関しては最適だと思いますが、それを証明するのは私の能力を超えています。少なくともそれは、私が文献で見つけたものよりもずっと単純です。
そして、最初の投稿以来、これがどのように機能するかについて ブログ投稿 を書きました。
通常のマージソートアルゴリズム-通常、n + m -1の比較を適用するマージステップ。一方のリストのサイズはnで、もう一方のリストのサイズはmです。このアルゴリズムを使用することは、2つのソートされたリストを組み合わせる最も簡単な方法です。
比較が高すぎる場合は、2つのことを実行できます。比較の数を最小限に抑えるか、比較のコストを最小限に抑えます。
比較コストの最小化に焦点を当てましょう。あなたとあなただけが、比較しているデータを量子化できるかどうかを決めることができます。それらを量子化できる場合、これはハッシュ方式を実装する形式であり、順序を維持しています。例えば。データを名前で比較する場合、最初のtname、...最初に「Klaehn、Ruediger」という名前のCharsを取得し、データ要素を「Kl.Ru」に削減/量子化できます。 "Packer、The"は順序 "Pa.Th"を保持します-削減された値を比較して、より安価な比較アルゴリズムを適用できます。しかし、別の「Kl.Ru」を見つけた場合、近い値になり、これらの要素を比較するより高価なアプローチに切り替えることができます。
この量子化された値をデータから抽出できる場合は、比較するよりも速く、これは最初に行うことです。量子化された値またはハッシュされた値を最初に比較します。この値は一度だけ計算する必要があるため、データ要素の作成時に計算できることに注意してください。
また、比較を最小限にするための別の方法についても触れました。
私は、このトピックに関する全10ページを含む古典的な本TAOCP- Volume 3-Sorting and Searching(pp.197-207、section 5.3.2)を調べました。 n + m-1の比較よりも高速なアルゴリズムへの参照が2つ見つかりました。
最初にファンリンマージアルゴリズムがあり、2番目はGlenn K Manacherによる改良です。両方ともTAOCPと、長さnおよびmの特別な条件で必要な比較の下限に近づくクリステンによるアルゴリズムによって引用されています。リストの。
ManacherのアルゴリズムはJournal of the ACM Vol。 26ページ434-440の3番:「 "Hwan-Lin"マージアルゴリズムの大幅な改善」。 m項目のリストとn項目のリストは異なる長さにすることができますが、m <= nを含む要素の数によっても必要です。
Hwang-Linアルゴリズムは、リストを分割して小さなリストに分割し、各サブリストの最初の要素を比較してリストを並べ替え、サブリストの一部の要素を比較する必要があるかどうかを判断します。最初のリストが2番目のリストよりも小さい場合、可能性が高く、長い方のリストの連続する要素を比較せずに結果のリストに転送できます。 small istの最初の要素が、分割された大きいリストの最初の要素より大きい場合、サブリストの前にあるすべての要素を比較せずにコピーできます。
ファンとリン(ベガ、フリーズ、サンタ)のマージalorithmの平均ケース分析 セクション2で、HLアルゴリズムの疑似コードを見つけることができます。私の説明よりもはるかに優れています。そして、比較が少ない理由がわかります。アルゴリズムは、バイナリ検索を使用して、インデックスを見つけ、短いリストから要素を挿入する場所を見つけます。
最後の例のようにリストがインターリーブされていない場合は、ほとんどの場合、残りのリストが小さく、残りのリストが大きいはずです。これは、HLアルゴリズムのパフォーマンスが向上する時期です。
2つの配列にN要素とM要素、N≥Mがあり、すべての要素が異なると仮定します。
ソートされた配列にNの要素xに続いてMの要素yが含まれている場合、またはその逆の場合、xとyが比較されている必要があります。 (たとえば、xとyの間に要素がないため、x <a <b <c <yであることがわかっている他の要素のチェーンa、b、cは存在できません。したがって、xとyは比較されているはずです。直接。
N> Mの場合、Mの各要素の前と後にNの要素が続く配列にすることができます。つまり、次のような非決定的な並べ替えアルゴリズムを使用しても比較する数値を完璧に推測します。 (つまり、Nが大きいと仮定します。M= 1。推測を確認してください)。