快速排序
1. 基本思想
快速排序是对冒泡排序的一种改进,采用分治法的思想,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序。
2. 排序流程
快速排序算法通过多次比较和交换来实现排序,以从小到大排序为例,其排序流程如下:
- 定义一个中值(一般是数组第一个元素),通过中值将数组分为两个部分
- 将小于等于中值的元素集中在数组左半部分,将大于等于中值的元素集中在数组右半部分
- 即数组的左半部分的值,均小于或等于中值,数组的右半部分的值,均大于或等于中值
- 此时,又可以将数组的左半部分作为一个新的数组,右半部分也作为一个新的数组,重复上述按中值将数组分为两个部分的过程
- 可以看出,此过程为递归过程,通过递归先将左半部分排好序,然后将右半部分排好序,即全数组都排好了序
3.排序步骤(图解)
下图只展示第一趟排序的过程,往下每一趟过程都重复此过程,只是数组的边界值发生变化
4.Java代码实现快速排序
4.1函数代码:
public static int[] quickSort(int arr[],int left,int right) {
int pivot = arr[left];//轴值
int i = left;//左下标
int j = right;//右下标
while (i < j) {
//在右边找到一个比中值小或者相等的值
while (i < j && arr[j] > pivot) {
j--;
}
//在左边找到一个比中值大或者相等的值
while (i < j && arr[i] < pivot) {
i++;
}
//在i和j没有相遇时,如果 arr[i] == arr[j] 此时让i+1
//即让arr[i+1] 与arr[j]进行交换 ,使两个相同的数在一起
if (arr[i] == arr[j] && i < j) {
i++;
} else {//交换
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
//左半部递归
if (i-1 > left) {
arr=quickSort(arr,left,i-1);
}
//右半部递归
if (j+1 < right) {
arr=quickSort(arr,j+1,right);
}
return arr;
}
4.2测试:
测试用例:4,6,1,3,2,5 (与上图用例一致)
public class QuickSort {
public static void main(String[] args) {
int[] arr = {4,6,1,3,2,5};
arr = quickSort(arr, 0, arr.length - 1);
System.out.println("经过快速排序后的结果为:" + Arrays.toString(arr));
}
}
测试结果:
5.算法分析
- 时间复杂度
- 最差:O(N^2),退化为冒泡排序
- 最优:O(NlogN)
- 平均:O(NlogN)
- 空间复杂度
- 递归调用消耗栈空间,因此为O(logN)
- 快排是一个不稳定的排序算法
- 33 33* 排序之后可能会变成 33* 33,即快速排序无法保证相等的元素的相对位置不变