挿入ソートのさまざまな実装に関していくつか質問があります。
実装1:
public static void insertionSort(int[] a) {
for (int i = 1; i < a.length; ++i) {
int key = a[i];
int j = i - 1;
while (j >= 0 && a[j] > key) {
a[j + 1] = a[j];
--j;
}
a[j + 1] = key;
}
}
実装2:
public static void insertionSort(int[] a) {
for (int i = 1; i < a.length; ++i) {
for (int j = i; j > 0 && a[j - 1] > a[j]; --j) {
swap(a, j, j - 1);
}
}
}
private static void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
これが私の最初の質問です。最初のバージョンは2番目のバージョンよりも少し速いはずですが(割り当てが少ないため)、そうではありません(または少なくとも違いはごくわずかです)。しかし、なぜ?
次に、JavaのArrays.sort()メソッドも2番目のアプローチを使用しているのではないかと思いました(おそらく、swapメソッドがさまざまな場所で使用されているため、コードが再利用されているためか、理解しやすいためです)。
実装3(binaryInsertionSort):
public static void binaryInsertionSort(int[] a) {
for (int i = 1; i < a.length; ++i) {
int pos = Arrays.binarySearch(a, 0, i, a[i]);
int insertionPoint = (pos >= 0) ? pos : -pos - 1;
if (insertionPoint < i) {
int key = a[i];
// for (int j = i; i > insertionPoint; --i) {
// a[j] = a[j - 1];
// }
System.arraycopy(a, insertionPoint, a, insertionPoint + 1, i - insertionPoint);
a[insertionPoint] = key;
}
}
}
バイナリ挿入は実用的なものですか、それとも理論的なものですか?小さなアレイでは、他のアプローチがはるかに高速であり、大きなアレイでは、mergesort/quicksortのパフォーマンスがはるかに優れています。