结论
- 对于近乎有序的数组,游标 j 近乎移不动,导致的问题是,下一次的partition要处理的元素是从 j 的右边到结束所有的元素;
- 在待排序的数据近乎有序的情况下,快速排序退化成O(n^2);
- 甚至由于递归的层数太多,会造成StackOverflowError的错误,在这种情况下,为了测试出算法的耗时,需要将虚拟机参数-Xss适当调大:-Xss10m;
测试代码
import java.util.Arrays;
public class Main {
// 比较Merge Sort和Quick Sort两种排序算法的性能效率
// 两种排序算法虽然都是O(nlogn)级别的, 但是Quick Sort算法有常数级的优势
// Quick Sort要比Merge Sort快, 即使我们对Merge Sort进行了优化
public static void main(String[] args) {
int N = 1000000;
// 测试1 一般性测试
System.out.println("Test for random array, size = " + N + " , random range [0, " + N + "]");
Integer[] arr1 = SortTestHelper.generateRandomArray(N, 0, N);
Integer[] arr2 = Arrays.copyOf(arr1, arr1.length);
SortTestHelper.testSort("_03.sorting_advanced._05.quick_sort.MergeSort", arr1);
SortTestHelper.testSort("_03.sorting_advanced._05.quick_sort.QuickSort", arr2);
System.out.println();
// 测试2 测试近乎有序的数组
// 但是对于近乎有序的数组, 我们的快速排序算法退化成了O(n^2)级别的算法
// 思考一下为什么对于近乎有序的数组, 快排退化成了O(n^2)的算法? :)
int swapTimes = 100;
assert swapTimes >= 0;
System.out.println("Test for nearly ordered array, size = " + N + " , swap time = " + swapTimes);
arr1 = SortTestHelper.generateNearlyOrderedArray(N, swapTimes);
arr2 = Arrays.copyOf(arr1, arr1.length);
SortTestHelper.testSort("_03.sorting_advanced._05.quick_sort.MergeSort", arr1);
SortTestHelper.testSort("_03.sorting_advanced._05.quick_sort.QuickSort", arr2);
return;
}
}
输出:
Test for random array, size = 1000000 , random range [0, 1000000]
MergeSort : 475ms
QuickSort : 350ms
Test for nearly ordered array, size = 1000000 , swap time = 100
MergeSort : 94ms
QuickSort : 21513ms