最小数の比較で2つのソートされた配列をマージするアルゴリズム


24

サイズnおよびmのタイプTの 2つのソートされた配列abが与えられます。2つの配列を(最大サイズn + mの)新しい配列にマージするアルゴリズムを探しています。

安価な比較操作がある場合、これは非常に簡単です。1つまたは両方の配列が完全に走査されるまで、最初の要素が最も低い配列から取り出し、残りの要素を追加します。このようなもの/programming/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回の比較を実行する必要があります。

サイズの違いが大きいリストに対しては、バイナリ検索を使用して、小さな配列の要素を大きな配列に挿入することで、かなりうまくいくはずです。しかし、両方のリストが同じサイズでインターリーブされている場合、それは適切に低下しません。

要素で利用できるのは(合計)順序関数のみであるため、比較を安価にするスキームは不可能です。

何か案は?

私はScalaこのビットを思いつきました。比較の数に関しては最適であると思いますが、それを証明する能力を超えています。少なくとも、私が文献で見つけたものよりもずっと簡単です。

そして、最初の投稿以来、これがどのように機能するかについてのブログ投稿を書きました。


2
「単純なマージアルゴリズム」ほど比較を少なくする方法はありません。あなたが最初に言及したようなエッジケースを処理しようとすることができますが、これは平均的なケースを悪化させます。
Mephy 14

5
@Mephy:私たちを啓発し、正式な証明をください。または、できない場合は、コメントを削除(または少なくとも改良)することを検討してください。
Doc Brown 14

4
@DocBrown正式な証拠があれば、コメントではなく答えを出します。とにかく、線形よりも優れたソリューションを見つけるには少なくとも線形時間が必要になるため、それは非常に明白な線形問題です。
Mephy 14

4
@Mephy:時間をかけて以下の答えを読んで、あなたが書いたことをよく考えてください。
ドックブラウン14

4
@Mephy明らかなほとんどのこと(「O(n ^ 2)未満で乗算を行うことはできません」、「選択したドアを変更しても、価格を勝ち取るチャンスは向上しません」、「できる「O(n log n)」未満でソートしない」、..)が間違っています。たとえば、短いリストでバイナリ検索アプローチを使用すると、平均的なケースが改善される可能性があります。
Voo 14

回答:


31

通常のマージソートアルゴリズム-通常はn + m -1比較を適用するマージステップ。1つのリストのサイズはnで、もう1つのリストのサイズはmです。このアルゴリズムを使用することは、2つのソートされたリストを結合するための最も簡単なアプローチです。

比較のコストが高すぎる場合、2つのことを行うことができます-比較の回数を最小限に抑えるか、比較のコストを最小限に抑えます。

比較コストの最小化に焦点を当てましょう。あなたとあなただけが、比較しているデータを量子化できるかどうかを決めることができます。それらを量子化できる場合、これはハッシュメソッドを実装する形式であり、順序を維持しています。たとえば、データが名前で比較され、次に最初のtnameである場合、...最初の名前を「Klaehn、Ruediger」という名前のCharsにし、データ要素を「Kl.Ru」に縮小/量子化できます。 「Packer、The」に、順序「Pa.Th」を保持します-これで、より安価な比較アルゴリズムを適用して、減少した値を比較できます。しかし、別の "Kl.Ru"が見つかった場合は、ほぼ価値があり、これらの要素を比較するより高価なアプローチに切り替えることができます。

データからこの量子化された値を比較するよりも速く抽出できる場合、これが最初に行うことです。最初に量子化またはハッシュされた値を比較します。この値は一度だけ計算する必要があるため、データ要素の作成時に計算できることに注意してください。

また、比較を最小限に抑える別の方法についても言及しました。

私は古典的な本TAOCP- Volume 3-Sorting and Searching(pp.197-207、セクション5.3.2)に目を通しました。n + m-1比較よりも高速なアルゴリズムへの2つの参照が見つかりました。

1つ目はHwang-Linマージアルゴリズムで、2つ目はGlenn K Manacherによる改善です。両方ともTAOCPにより引用され、長さnとmの特別な条件で必要な比較の下限に近づくChristenによるアルゴリズムです。リストの。

Manacherのアルゴリズムは、Journal of the ACM Vol。26 434〜440ページの3番:「「Hwan-Lin」マージアルゴリズムの大幅な改善」。m個のアイテムを持つリストとn個のアイテムを持つリストは異なる長さにすることができますが、m <= nを含む要素の数によってそれらをオーダーする必要があります

Hwang-Linアルゴリズムは、リストを分割してマージし、小さなリストに分割し、各サブリストの最初の要素を比較してリストをソートし、サブリスト内のいくつかの要素を比較する必要があるかどうかを決定します。最初のリストが2番目のリストよりも小さい場合、可能性が高く、長いリストの連続した要素を比較せずに結果のリストに転送できます。small istの最初の要素が、分割された大きいリストの最初の要素よりも大きい場合、サブリストの前にあるすべての要素を比較せずにコピーできます。

セクション2 のHwangとLin(Vega、Frieze、Santha)の統合されたアロリズムの平均ケース分析では、HLアルゴリズムの擬似コードを見つけることができます。これは私の説明よりもはるかに優れています。そして、なぜ比較が少ないのかを見ることができます-アルゴリズムはバイナリ検索を使用してインデックスを見つけ、短いリストから要素を挿入する場所を見つけます。

リストが最後の例のようにインターリーブされていない場合、ほとんどの場合、残りのリストは小さく、残りのリストは大きくなります。これは、HLアルゴリズムのパフォーマンスが向上し始めるときです。


これについてのコメントをありがとうございます-私は私の答えを確認し、Knuthがこのトピックについて10ページすべてを費やしていることを発見しました。そして、私は本棚からJACMを取り出して、さらに前を見ていた。答えを改善します。-ダウン投票の必要はありません。ハッシュ(量子化)アルゴリズムは単純なアイデアであり、多くのデータセットに適用できます-ただし、データに適用できるかどうかを判断するのは、質問したGuyだけです。
ザパッカー14

4
答えを改善した後、あなたに投票したすべての人が再びあなたに投票する機会を得ます;
Doc Brown 14

+1は、サイズが非常に異なる場合、標準マージが最適ではないことに注意してください。
フロリアンF 14

1

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の要素が続く配列を持つことができます。これは、少なくとも2Mの比較が必要であることを意味します。比較する数値を完全に推測します。(つまり、Nが大きく、M = 1であると仮定します。バイナリ検索はO(log2 N)ステップかかります。非決定論的なアルゴリズムは、2番目の配列の1つの要素がどちらの2つの要素に属するかを推測し、2つの比較を行います推測を確認してください)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.