我使用我的Merge sort和Radix排序实现了一百万个随机正数,长度约为20位。 合并排序显着,几乎是Radix排序的6倍。
我理解Radix排序的时间复杂度也取决于整数的位数,但我的合并实现在所有输入大小上击败了我的Radix实现。
我正在使用我自己的队列类,它在我的基数排序中具有常量时间push()和pop()。我在合并排序中使用数组。这与此有关吗?
public static void RadixSort(long arr[]) {
//Using 10 queues for each digit from 0-9.
Queue q[] = new Queue[10];
for (int i = 0; i < 10; i++)
q[i] = new Queue();
boolean allNumbersNotBucketed = true;
long divisor = 1;
while (allNumbersNotBucketed) {
allNumbersNotBucketed = false;
for (int i = 0; i < arr.length; i++) {
long digit = (arr[i] / divisor) % 10;
q[(int) digit].enqueue(arr[i]);
//Put number into appropriate queue.
if(digit > 0) allNumbersNotBucketed = true;
}
int pos = 0;
divisor *= 10;
for (int i = 0; i < 10; i++)
while (!q[i].isEmpty())
arr[pos++] = q[i].dequeue();
//Put queue contents back into array
}
}
这是合并排序
public static void mergeSort(long[] a) {
long[] tmp = new long[a.length];
mergeSort(a, tmp, 0, a.length - 1);
}
private static void mergeSort(long[] a, long[] tmp, int left, int right) {
if (left < right) {
int center = (left + right) / 2;
mergeSort(a, tmp, left, center); //Divide 0 to middle
mergeSort(a, tmp, center + 1, right); // Divide middle to center
merge(a, tmp, left, center + 1, right); //Merge sorted lists
}
}
private static void merge(long[] a, long[] tmp, int left, int right,
int rightEnd) {
long leftEnd = right - 1;
int k = left;
long num = rightEnd - left + 1;
//Put smallest element into tmp while both lists
//are non empty.
while (left <= leftEnd && right <= rightEnd)
if (a[left] < a[right])
tmp[k++] = a[left++];
else
tmp[k++] = a[right++];
while (left <= leftEnd)
// Copy rest of first half
tmp[k++] = a[left++];
while (right <= rightEnd)
// Copy rest of right half
tmp[k++] = a[right++];
// Copy tmp back
for (long i = 0; i < num; i++, rightEnd--)
a[rightEnd] = tmp[rightEnd];
}
修改 我愚蠢地使用LinkedList样式队列。我将其更改为使用本机数组,现在合并排序的速度仅为之前的6倍。即使对于只有10位数的数字,合并排序仍然更快。我猜BigO常数在这里发挥作用。对push()和pop()的数百万次函数调用也可以归咎于此。