【发布时间】:2016-04-04 17:15:03
【问题描述】:
我尝试在 Java 中实现一种高效的排序算法。为此,我还实现了快速排序并使用以下代码:
public class Sorting {
private static Random prng;
private static Random getPrng() {
if (prng == null) {
prng = new Random();
}
return prng;
}
public static void sort(int[] array) {
sortInternal(array, 0, array.length - 1);
}
public static void sortInternal(int[] array, int start, int end) {
if (end - start < 50) {
insertionSortInternal(array, start, end);
} else {
quickSortInternal(array, start, end);
}
}
private static void insertionSortInternal(int[] array, int start, int end) {
for (int i=start; i<end - 1; ++i) {
for (int ptr=i; ptr>0 && array[ptr - 1] < array[ptr]; ptr--) {
ArrayUtilities.swap(array, ptr, ptr - 1);
}
}
}
private static void quickSortInternal(int[] array, int start, int end) {
int pivotPos = getPrng().nextInt(end - start);
int pivot = array[start + pivotPos];
ArrayUtilities.swap(array, start + pivotPos, end - 1);
int left = start;
int right = end - 2;
while (left < right) {
while (array[left] <= pivot && left < right) {
++left;
}
if (left == right) break;
while (array[right] >= pivot && left < right) {
right--;
}
if (left == right) break;
ArrayUtilities.swap(array, left, right);
}
ArrayUtilities.swap(array, left, end - 1);
sortInternal(array, start, left);
sortInternal(array, left + 1, end);
}
}
ArrayUtilities.swap 只是交换数组中的两个给定元素。从这段代码中,我期望 O(n log(n)) 运行时行为。但是,要排序的一些不同长度的数组会产生以下结果:
10000 个元素:32 毫秒
20000 个元素:128 毫秒
30000 个元素:296 毫秒
测试在每种情况下运行 100 次,然后计算运行次数的算术平均值。但显然,与预期的行为相反,运行时是O(n^2)。我的算法有什么问题?
【问题讨论】:
-
Quicksort 当然有
O(n lg n)最佳情况 性能,但也有O(n^2)worst case performance。为什么您希望在基准测试中获得最佳案例性能? (当然假设您使用 JMH 进行了基准测试,而不是手动进行,在这种情况下,无论如何这些数字可能毫无意义) -
如何填充输入数组?看起来您的快速排序对重复元素没有任何智能处理,因此如果输入有很多重复元素,性能将下降到 O(n^2)。
-
@blazs 抱歉;但你想告诉我什么?
-
抱歉。我想确保 OP 在给定长度的同一数组上重复时间测量 100 次。 (由于运行时间分析与输入无关,这应该无关紧要,但让我们看看实验是如何完成的。也许这可以提示我们问题出在哪里。)
标签: java algorithm big-o quicksort