web-dev-qa-db-ja.com

分割統治アルゴリズム– 2つ以上の部分に分割しないのはなぜですか?

クイックソートやマージソートなどの分割統治アルゴリズムでは、入力は通常(少なくとも導入テキストでは)twoに分割され、2つの小さいデータセットは再帰的に処理されます。これは、2つの半分がデータセット全体を処理する作業の半分未満しかかからない場合、問題をより速く解決できることを私には意味があります。しかし、なぜデータセットを3つの部分に分割しないのでしょうか。四? n

多くの多くのサブセットでデータを分割する作業は価値がないと思いますが、2つのサブセットで停止する必要があることを理解する直感に欠けています。

また、3ウェイクイックソートへの言及もたくさんあります。これはいつ速くなりますか?実際に何が使用されていますか?

33
beta

これは、2つの半分がデータセット全体を処理する作業の半分未満しかかからない場合、問題をより速く解決できることを私には意味があります。

つまり、分割統治アルゴリズムの本質ではありません。通常のポイントは、アルゴリズムが「データセット全体を扱う」ことがまったくできないということです。代わりに、(2つの数値の並べ替えのように)簡単に解決できる断片に分割され、それらは簡単に解決され、結果は完全なデータセットのソリューションを生成する方法で再結合されます。

しかし、なぜデータセットを3つの部分に分割しないのでしょうか。四?ん?

主にそれを3つ以上の部分に分割し、3つ以上の結果を再結合すると、実装はより複雑になりますが、アルゴリズムの基本的な(Big O)特性は変更されません-違いは一定の要因であり、結果としてスローダウンする可能性があります3つ以上のサブセットの分割と再結合により追加のオーバーヘッドが発生する場合。

たとえば、3ウェイマージソートを行う場合、再結合フェーズでは、すべての要素について最大3つの要素を見つける必要があるため、1ではなく2つの比較が必要なので、全体で2倍の比較を実行します。 。代わりに、再帰の深さをln(2)/ ln(3)== 0.63の因数で減らします。したがって、スワップは37%少なくなりますが、2 * 0.63 == 26%多い比較(およびメモリアクセス)になります。それが良いか悪いかは、ハードウェアのどちらがより高価であるかに依存します。

また、3ウェイクイックソートへの言及もたくさんあります。これはいつ速くなりますか?

どうやら quicksortのデュアルピボットバリアント は、同じ数の比較を必要とすることが証明できますが、スワップの平均が20%少ないため、純利益になります。

実際に何が使用されていますか?

最近では、自分の並べ替えアルゴリズムをプログラミングする人はほとんどいません。ライブラリが提供するものを使用します。たとえば、 Java 7 API は実際にはデュアルピボットクイックソートを使用します。

何らかの理由で実際に独自の並べ替えアルゴリズムを実際にプログラムする人は、単純な2ウェイバリアントに固執する傾向があります。これは、エラーの可能性が低く、ほとんどの場合、パフォーマンスが20%優れているためです。覚えておいてください。最も重要なパフォーマンスの改善は、コードが「機能していない」から「機能している」場合です。

49

漸近的に言えば、それは問題ではありません。たとえば、バイナリ検索はほぼログになります2n個の比較。3値検索では、ほぼ対数n個の比較。対数がわかっていれば、その対数もわかるax =ログbx /ログba、したがって、バイナリ検索は約1/logしか作成しません2≈三項検索の1.5倍の比較。これは、だれも対数の底を大きなOh表記で指定しない理由でもあります。これは、実際の底が何であっても、常に特定の底の対数から一定の係数です。したがって、問題をより多くのサブセットに分割しても、時間の複雑さは改善されず、実際には、より複雑なロジックを上回るには不十分です。実際、その複雑さは実際のパフォーマンスに悪影響を及ぼし、キャッシュのプレッシャーを増大させたり、マイクロ最適化を実行不可能にする可能性があります。

一方、一部のツリーっぽいデータ構造は、通常は他の理由ですが、高い分岐係数(3をはるかに超える、多くの場合32以上)を使用します。これはメモリ階層の利用率を向上させます。RAMに保存されたデータ構造はキャッシュをより有効に利用します。ディスクに保存されたデータ構造はHDD-> RAMの読み取りが少なくて済みます。

30
user7043

2つではなくNで細分する検索/ソートアルゴリズムがあります。

簡単な例は、O(1)時間を要する)ハッシュコーディングによる検索です。

ハッシュ関数が順序を維持する場合、これを使用してO(N)ソートアルゴリズムを作成できます(任意のソートアルゴリズムは、数値が必要な場所をN回検索するだけと考えることができます結果に入ります。)

基本的な問題は、プログラムがいくつかのデータを調べていくつかの後続の状態に入るとき、いくつの後続の状態があり、それらの確率がどれだけ等しいかということです。

コンピュータが2つの数値を比較し、たとえばジャンプするかしないかを判断する場合、両方のパスが等しい可能性があると、プログラムカウンタは各パスについてもう1ビットの情報を「認識」し、平均して1つを「学習」します。ビット。問題がMビットの学習を必要とする場合、バイナリ決定を使用すると、Mより少ない決定で答えを得ることができません。したがって、たとえば、サイズが1024のソートされたテーブルで数値を検索することは、10未満のバイナリ決定では実行できません。それは、少数では十分な結果が得られないためですが、それ以上のことは可能です。

コンピューターが1つの数値を取り、それをインデックスに変換して配列に変換すると、配列内の要素数の2を底とする対数まで「学習」し、一定の時間で実行します。たとえば、1024エントリのジャンプテーブルがある場合は、多かれ少なかれ同じように、そのテーブルをジャンプして10ビットを「学習」します。これがハッシュコーディングの背後にある基本的なトリックです。この並べ替えの例は、一連のカードを並べ替える方法です。各カードに1つずつ、52のビンがあります。各カードをビンに投げ入れ、すくい上げます。細分化は必要ありません。

4
Mike Dunlavey

これは並べ替えだけでなく、一般的な分割統治に関する質問なので、誰も マスター定理 を取り上げていないことに驚いています

簡単に言うと、分割統治アルゴリズムの実行時間は、大きな問題を小さな問題に変えることで得られる利点と、より多くの問題を解決するために支払う代償の2つの相反する力によって決まります。アルゴリズムの詳細に応じて、問題を2つ以上の部分に分割するために支払うかどうかは異なります。各ステップで同じ数のサブ問題に分割し、各ステップで結果を組み合わせる時間の複雑さを知っている場合、マスター定理はアルゴリズム全体の時間の複雑さを教えてくれます。

乗算の Karatsuba アルゴリズムは、3-way divide and conquerを使用して、通常の乗算​​アルゴリズム(nは数字の桁数です)。

1