快速排序是一种不稳定的原地交换排序(据说可以改进),其平均时间复杂度是 O(nlogn)。最坏情况下是O(n^2)。
当数组已是有序或接近有序时,是最坏的情况。在示例算法中,总是选取当前块的第一个元素作为key,当数组已经有序时,一趟排序总是把数组分成一个元素和其他元素两部分(没有发挥分治的效果)。这时对n个元素的数组的排序要操作的次数是 n!。
所以要避免最坏的情况,key的选择至关重要。我们可以通过随机选择key解决这个问题。
示例代码如下:
public class Quicksort3 {
//调用时传参sort(arr,0,arr.length-1);
public static void sort(int [] arr, int left, int right) {
if(left>=right) {
//已经分割数组到最小了,递归结束
return;
}
/*
* for循环完成一趟排序,
* key、i、j指向数组下标
* key选取第一个元素,
* i指向key,i总是指向<=key的元素下标。并且i左边的元素也<=key
* j从left+1向right遍历元素
*/
int i = left,key = left;
for(int j = left+1; j <= right; j++){
/*
* 这里的逻辑是 如果j遍历到比arr[key]小的元素就和 arr[i+1]交换,
* (i下标的左边总是>key).j遍历完后数组就以i为界分成两份(一边大,一边小。妥妥的)
* */
if(arr[j] < arr[key]){
i++;
int k = arr[j];
arr[j] = arr[i];
arr[i] = k;
}
}
int k = arr[key];
arr[key] = arr[i];
arr[i] = k;
//递归分治
sort(arr,key,i-1);
sort(arr,i+1,right);
}
}