質問のタイトルごとに、配列の長さが奇数で、配列要素に1〜10の番号が付けられている場合.
例、
3 6 8 1 3 7 7 9 4 1
heapsort?の使用を考えていました。これは配列であるため、-マージソートおよび挿入ソートはシフトが必要であり、それほど効率的ではありません。
配列要素は1〜10の数字です。
この制限により、 counting sort は汎用ソートアルゴリズムよりもはるかに効率的です-O(n)
これは私のカウントソートの例です
static int[] countingSort(int[] numbers) {
int max = numbers[0];
for (int i = 1; i < numbers.length; i++) {
if (numbers[i] > max)
max = numbers[i];
}
int[] sortedNumbers = new int[max+1];
for (int i = 0; i < numbers.length; i++) {
sortedNumbers[numbers[i]]++;
}
int insertPosition = 0;
for (int i = 0; i <= max; i++) {
for (int j = 0; j < sortedNumbers[i]; j++) {
numbers[insertPosition] = i;
insertPosition++;
}
}
return numbers;
}
エレメントが10個しかない場合は、心配することもありません。百万がある場合、それは重要になり始める可能性があります。
編集:要素の範囲が1〜10のみであるという制約がある場合、カウントソートはおそらく最適です。この問題に適用されるカウントソートは、O(n)時間で実行されます。マージソート(以下で推奨)は、O(nlogn)時間。カウントソートの並列化は興味深い可能性があります。n/ p要素のサブ配列を各プロセッサに割り当てるだけです。各プロセッサはサイズ9の独自のcount配列を持ちます。このステップはO(n/p) time。次に、すべてのcount配列を単一の配列に統合します。これには、O(p) time。の最後のステップを十分に検討していません。要素が順番に配置されているカウントソートですが、count配列の要素がアトミックである限り、元の配列のn/pセクションを個々のプロセッサに割り当てて、並列化を実現できます。ただし、count配列の要素は、同時実行性を大幅に低下させる可能性があります。count配列のサブセクションをp個のプロセッサに割り当てることができ、O(n/p) runt ime、要素がかなり均等に分散されている場合、10個のプロセッサに制限されます。要素が均等に分散されていない場合、1つ以上のプロセッサが作業の大部分を実行している可能性があります。これは素晴らしい質問です。 O(n/p)時間でカウントソートを行うことはできますか?
クイックソートは、高速で実行され、メモリを節約する優れたインプレースソートアルゴリズムです。ただし、要素の範囲が1〜10のみである場合、多数の要素を並べ替えると、最初または並べ替えの途中で同じ数の大きな実行が行われます。順序付けられた配列またはサブ配列は、クイックソートのパフォーマンスを本当に低下させる可能性があります。
メモリを気にしない場合は、単純なマージソートで十分です。 Mergesortは、最速の標準ソートアルゴリズムを備えています。
Java 7のデフォルトのCollections.sort()実装は、「TimSort」から適応したMergesortアルゴリズムです。Java 7のデフォルトのArrays.sort()実装デュアルピボットクイックソートです。
並列にしたい場合、Parallel Quicksortを使用すると、少数のプロセッサを備えた大きなアレイで良好な結果を得ることができますが、シーケンシャルQuicksortと同じ制限があります。 PSRSは、より多くのプロセッサに拡張するのに役立ちます。
複雑さのグラフについてはこちらをご覧ください 複雑さ比較チャート 。
並べ替えアルゴリズムの比較は、時間とスペースの複雑さのベスト、アベレージ、ワーストケースシナリオに基づいています。このグラフに基づいて、 Counting Sort アプローチがスペースと時間の複雑さの両方で最適であることがわかります。他の同等の方法は、基数ソートです。
「カウントソート」の最悪の[時間、スペース]複雑さ:-[O(n + k)、O(k)]。
「基数ソート」の最悪の[時間、スペース]複雑さ:-[O(nk)、O(n + k)]。
QuickSortは、分割統治アルゴリズムです。要素をピボットとして選択し、指定された配列を選択されたピボットの周りに分割してから、プロセスを繰り返します。さまざまな方法でピボットを選択するquickSortにはさまざまなバージョンがあります
このシナリオでは、ソートのカウントが最適です。
データが0〜kの範囲の整数であると仮定します。サイズKの配列を作成して、表示されるアイテムの数を追跡します(値0の3つのアイテム、値1の4つのアイテムなど)。この数を考えると、アイテムの位置を知ることができます。すべての1は0の後に来る必要があり、そのうち3つあります。したがって、1はアイテム#4から始まります。したがって、アイテムをスキャンし、適切な位置に挿入できます。
カウント配列の作成はO(N)適切な位置にアイテムを挿入することはO(N)ここで単純化しすぎています—カウントの合計があります。そして、ソートを安定させる最大から最小の順序付け。
これは単純なソートの例です(挿入ソート)
private static void insertionSort(int[] a) {
// [230, 23, 45, 34, 98]
for (int j = 2; j < a.length; j++) {
int key = a[j];
int i = j - 1;
while (i > 0 && a[i] > key) {
a[i + 1] = a[i];
i--;
}
a[i + 1] = key;
}
System.out.println("sorted array: " + Arrays.toString(a));
}