ソートするデータの分布(統計的な意味で)について何か知っている場合、その情報を考慮に入れると、ソートアルゴリズムのパフォーマンスが向上する可能性があります。
だから私の質問は、その種の情報を考慮に入れるソートアルゴリズムはありますか?彼らはどれくらい良いですか?
編集:明確にするための例:データの分布がガウス分布であることがわかっている場合は、データを処理するときにその場で平均と平均を推定できます。これにより、各番号の最終的な位置の見積もりが得られます。これを使用して、番号を最終的な位置の近くに配置できます。
編集#2:答えがこの問題について議論している詳細なページへのwikiリンクではないことにかなり驚いています。これは非常に一般的なケース(たとえば、ガウスのケース)ではありませんか?
編集#3:私は推測ではなく、情報源で明確な答えを探しているので、この質問に賞金を追加しています。 「ガウス分布データの場合、Smith et al。[1]によって証明されたように、XYZアルゴリズムは平均して最速です」のようなものです。ただし、追加情報は大歓迎です。
注:最も投票数の多い回答に賞金を授与します。賢く投票してください!
並べ替えるデータの分布がわかっている場合は、バケットソートアルゴリズムを使用します。それにいくつかのロジックを追加して、分布のプロパティに基づいてさまざまなバケットのサイズや位置を計算することができます(例:ガウス分布の場合、平均から(シグマ/ k)離れた場所にバケットがある可能性があります。ここで、シグマは分布の標準偏差です)。
既知の分布を持ち、このように標準のバケットソートアルゴリズムを変更することで、おそらくヒストグラムソートアルゴリズムまたはそれに近い何か。もちろん、分布がわかっているので、最初のパス(リンクで説明)を実行する必要がない可能性があるため、アルゴリズムはヒストグラムソートアルゴリズムよりも計算が高速になります。
編集:質問の新しい基準が与えられた場合(ヒストグラムの並べ替えに関する以前の回答は立派なNISTにリンクしており、パフォーマンス情報が含まれていますが)、ここに並列処理に関する国際会議の査読ジャーナル記事:
著者は、このアルゴリズムのパフォーマンスが一般的なクイックソートアルゴリズムよりも優れている(最大30%優れている)と主張しています。
読みたいと思うかもしれません 自己改善アルゴリズム :任意の入力分布に対して最終的に最適な予想実行時間を達成します。
2つの問題に対して、このような自己改善アルゴリズムを提供します。(i)一連の数値を並べ替えることと、(ii)平面点セットのドロネー三角形分割を計算することです。どちらのアルゴリズムも、予想される最適な制限の複雑さを実現します。アルゴリズムは、入力分布に関する情報を収集するトレーニングフェーズで始まり、アルゴリズムが最適化された化身に落ち着く定常的なレジームが続きます。
入力分布がほぼガウス分布であることがすでにわかっている場合は、スペースの複雑さの観点からは別のアプローチの方が効率的かもしれませんが、予想される実行時間の観点からは、これはかなり素晴らしい結果です。
データソースの分布がわかれば、優れたハッシュ関数を作成できます。分布をよく知っていると、ハッシュ関数は完全なハッシュ関数であるか、多くの入力ベクトルに対してほぼ完全であることがわかる場合があります。
このような関数は、サイズnの入力をn個のビンに分割し、最小のアイテムが最初のビンにマップされ、最大のアイテムが最後のビンにマップされるようにします。ハッシュが完璧な場合、すべてのアイテムをビンに挿入するだけで並べ替えが可能になります。
すべてのアイテムをハッシュテーブルに挿入し、順序で抽出すると、ハッシュが完全な場合はO(n)になります(ハッシュ関数の計算コストがO(1)であり、下線が付いていると仮定)ハッシュデータ構造の操作はO(1))です。
ハッシュテーブルを実装するには、フィボナッチヒープの配列を使用します。
ハッシュ関数が完全ではない(ただし、まだ完全に近い)入力ベクトルの場合、O(nlogn)よりもはるかに優れています。完璧な場合、O(n)になります。平均の複雑さを計算する方法がわかりませんが、強制された場合は、O(nloglogn)に賭けます。
コンピュータのソートアルゴリズムは、比較ベースのソートと非比較ベースのソートの2つのカテゴリに分類できます。比較ベースの並べ替えの場合、最良の場合の並べ替え時間はΩ(nlogn)ですが、最悪の場合の並べ替え時間はO(n2)まで上昇する可能性があります。近年、データ分布特性に応じた高度なクイックソートなど、比較ベースのソートを高速化するために、いくつかの改良されたアルゴリズムが提案されています。ただし、これらのアルゴリズムの平均ソート時間はわずかΩ(nlog2n)であり、最良の場合にのみO(n)に到達できます。比較ベースのソートとは異なり、カウントソート、バケットソート、基数ソートなどの非比較ベースのソートは、主にキーとアドレスの計算に依存します。キーの値が1からmの範囲で有限である場合、非比較ベースのソートの計算の複雑さはO(m + n)です。特に、m = O(n)の場合、ソート時間はO(n)に達する可能性があります。ただし、m = n2、n3、…。の場合、線形ソート時間の上限は取得できません。非比較ベースのソートでは、バケットソートは、類似したキーを持つレコードのグループを適切な「バケット」に分散し、次に別のソートアルゴリズムが各バケットのレコードに適用されます。バケットソートを使用すると、レコードをm個のバケットに分割するのにかかる時間が短縮されますが、各バケットに含まれるレコードはわずかであるため、「クリーンアップソート」アルゴリズムを非常に高速に適用できます。したがって、バケットソートは、Ω(nlogn)アルゴリズムと比較して、ソート時間を漸近的に節約できる可能性があります。明らかに、すべてのレコードをバケットに均一に分散する方法は、バケットソートで重要な役割を果たします。したがって、必要なのは、データ分散に従ってハッシュ関数を構築する方法です。これは、各レコードのキーに基づいて、n個のレコードをn個のバケットに均一に分散するために使用されます。したがって、提案されたバケットソートアルゴリズムのソート時間は、どのような状況でもO(n)に達します。
このペーパーを確認してください: http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=5170434&tag=1
バケットソートは、O(1)時間内の各ポイントのCDFを計算できる限り、線形時間ソートアルゴリズムを提供します。
他の場所でも検索できるアルゴリズムは次のとおりです。
a = array(0, n - 1, []) // create an empty list for each bucket
for x in input:
a[floor(n * cdf(x))].append(x) // O(1) time for each x
input.clear()
for i in {0,...,n - 1}:
// this sorting step costs O(|a[i]|^2) time for each bucket
// but most buckets are small and the cost is O(1) per bucket in expectation
insertion_sort(a[i])
input.concatenate(a[i])
実行時間はO(n)期待値です。これは、期待値にO(n)ペア(x、y)があり、xとyが含まれるためです。同じバケットであり、挿入ソートの実行時間は正確にO(n +#同じバケット内のペア)です。分析は FKS静的完全ハッシュ の分析と同様です。
編集:分布がわからないが、それがどのファミリーからのものかはわかっている場合は、平均と分散を計算することでガウスの場合はO(n)で分布を推定し、同じアルゴリズムを使用できます(ちなみに、この場合の累積分布関数の計算は簡単ではありません)。
クイックソートでその情報を使用して、ピボット値を選択できます。これにより、アルゴリズムがO(N ** 2)の最悪の場合の複雑さから離れる確率が向上すると思います。
サイクルソート はこのカテゴリに分類されると思います。各要素を最終的に配置する正確な位置がわかっている場合に使用します。
Cyclesortにはいくつかの優れたプロパティがあります。特定の制限されたタイプのデータに対して、各要素が最大で1回移動されることを保証しながら、線形時間で安定したインプレースソートを実行できます。