Java 6のArrays.sort
メソッドは、プリミティブの配列にはQuicksortを使用し、オブジェクトの配列にはマージソートを使用します。ほとんどの場合、クイックソートはマージソートよりも高速で、メモリの消費量も少ないと思います。私の実験は、両方のアルゴリズムがO(n log(n))ですが、それをサポートしています。では、なぜ異なるタイプに異なるアルゴリズムが使用されるのでしょうか?
Integer
か?
Java 6のArrays.sort
メソッドは、プリミティブの配列にはQuicksortを使用し、オブジェクトの配列にはマージソートを使用します。ほとんどの場合、クイックソートはマージソートよりも高速で、メモリの消費量も少ないと思います。私の実験は、両方のアルゴリズムがO(n log(n))ですが、それをサポートしています。では、なぜ異なるタイプに異なるアルゴリズムが使用されるのでしょうか?
Integer
か?
回答:
最も可能性の高い理由:クイックソートは安定していません。つまり、等しいエントリはソート中に相対的な位置を変更できます。特に、これは、既にソートされた配列をソートした場合、変更されないままになる可能性があることを意味します。
プリミティブ型にはIDがないため(同じ値を持つ2つのintを区別する方法はありません)、これはそれらにとって重要ではありません。ただし、参照型の場合、一部のアプリケーションで問題が発生する可能性があります。したがって、それらには安定したマージソートが使用されます。
OTOH、プリミティブ型に(保証されたn * log(n))安定したマージソートを使用しない理由は、配列のクローンを作成する必要があるためです。参照タイプの場合、参照されるオブジェクトは通常、参照の配列よりもはるかに多くのメモリを消費しますが、これは通常は問題になりません。ただし、プリミティブ型の場合、配列を完全に複製すると、メモリ使用量が2倍になります。
私が考えることができる1つの理由は、クイックソートがO(n ^ 2)の最悪の場合の時間の複雑さを持っているのに対し、マージソートはO(n log n)の最悪の場合の時間を保持することです。オブジェクト配列の場合、クイックソートが最悪の場合の1つのケースである、複数のオブジェクト参照が重複することが予想されます。
さまざまなアルゴリズムの適切な視覚的比較があります。さまざまなアルゴリズムの右端のグラフに特に注意してください。
私はアルゴリズムに関するコースラクラスを受講しており、講義の1つであるボブセジウィック教授はJavaシステムの評価について言及しています。
「プログラマーがオブジェクトを使用している場合、おそらくスペースは非常に重要な考慮事項ではなく、マージソートで使用される余分なスペースは問題ではない可能性があります。プログラマーがプリミティブ型を使用している場合は、パフォーマンスが最も重要であるため、クイックソート。」
java.util.Arraysの用途はクイックソート intやなどのプリミティブ型のためにマージソート実装するオブジェクトのための同等または使用Aを Comparatorをます。2つの異なる方法を使用するアイデアは、プログラマーがオブジェクトを使用している可能性がある場合、スペースはそれほど重要な考慮事項ではないため、mergesortが使用する余分なスペースは問題ではない可能性があり、プログラマーがプリミティブ型を使用している場合は、パフォーマンスが最も重要であるため、クイックソート。
例:これは、ソートの安定性が重要な場合の例です。
そのため、オブジェクトタイプ、特に変更可能なオブジェクトタイプと、ソートキーよりも多くのデータを持つオブジェクトタイプに対して、安定したソートが有効であり、mergesortはそのようなソートです。しかし、プリミティブ型の場合、安定性は無関係なだけではありません。意味がありません。
出典:INFO
JavaのArrays.sort
メソッドは、クイックソート、挿入ソート、およびマージソートを使用します。OpenJDKコードには、シングルとデュアルの両方のピボットクイックソートも実装されています。最速のソートアルゴリズムは状況に応じて異なり、勝者は次のとおりです。小さな配列の挿入ソート(現在選択されている47)、ほとんどのソートされた配列のマージソート、残りの配列のクイックソートなので、JavaのArray.sort()は最適なアルゴリズムを選択しようとしますそれらの基準に基づいて適用します。