一、原理
快速排序是排序算法中第二简单的算法,每次从待排序数组中选择一个基准值(正常选择第一个),然后将数组分为两部分,将比基准值小的移动到基准值左边去,比基准值大的移动到基准值右边去,这样一来基准值就排到了正确的位置。接下来对两个部分继续递归执行快速排序,直到所有元素有序。
二、java代码
public static void quickSort(int[] list, int left, int right){
if(left<right){
int base = division(list, left, right); // 拆分为两部分,base是已到达正确位置的基准元素
quickSort(list, left, base-1); // 对基准元素左边的待排数组递归执行快排
quickSort(list, base+1,right); // 对基准元素右边的待排数组递归执行快排
}
}
public static int division(int[] list, int left, int right){ // 将left到right之间的待排数组拆分为两部分
int base = list[left]; //选择第一个元素作为基准元素
while(left<right){ // 当left和right为重合时,说明没有扫描完毕所有的元素,继续执行此过程
while(left<right&&list[right]>=base) //从right位置开始往左扫描,直到找到一个比基准值小的元素
right--;
list[left] = list[right]; // 将此元素移动到left位置处
while(left<right&&list[left]<=base) //然后从left位置开始往右扫描,直到找到一个比基准值大的元素
left++;
list[right] = list[left]; // 将此元素移动到right处
}
list[left] = base; // 最后将基准元素放到正确的位置上去。此时left和right实际上相等
return left; // 返回基准元素的位置
}
三、总结
- 快速排序是一种不稳定的交换排序算法
- 数组已排序时,拆分操作的左子序列会为空,此时时间复杂度最差,需要执行N次拆分操作(外部循环),每个拆分操作内部需要扫描N次(实际上是N次、N-1次、N-2次…), 因此合计为 O(N2)
- 数据随机分布时,拆分操作类似二分法,需要执行log2N次,因此时间复杂度为 O(Nlog2N)
- 因此平均时间复杂度为 O(Nlog2N)
- 额外空间主要是存放基准元素,一共需要 O(Nlog2N)