1. 算法思想
快速排序采用分治法的策略,下面应用快速排序对一个记录序列( ~
)进行升序排序,其基本思想如下:
- 划分:选定一个记录作为轴值,以轴值为基准将整个序列划分为两个子序列
~
和
~
,轴值的位置
在划分的时候确定,并且前一个子序列中的记录都小于或等于轴值,后一个子序列中的记录都大于或等于轴值。
- 求解子问题:分别对划分后的每一个子序列递归处理。
- 合并:由于对于子序列
~
和
~
的排序是就地进行的,所以合并不需要执行任何操作。
2. 具体过程
- 首先对待排序记录序列进行划分,以第一个记录为轴值进行划分
- 以轴值为基准将排序序列划分为两个子序列后,对每一个子序列分别递归进行处理
3. 动画演示
红色区域表示轴值,下面表示第一次划分的结果:

4. 代码实现
/**
* @author created by linjunhao
* @date 2020/3/26
* @description 快速排序
*/
public class QuickSort {
public void sort(int[] values, int start, int end) {
int pivot;
if (start < end) {
//划分并获取轴值
pivot = partition(values, start, end);
//求解子问题,对左侧序列进行快速排序
sort(values, start, pivot - 1);
//求解子问题,对右侧序列进行快速排序
sort(values, pivot + 1, end);
}
}
/**
* 划分并返回轴值
* @param values 待划分记录
* @param start
* @param end
* @return
*/
public int partition(int[] values, int start, int end) {
//双引用,分别从两端交替扫描
int i = start, j = end;
while (i < j) {
//从尾端开始扫描
while (i < j && values[i] <= values[j]) j--;
//交换,将较小的记录放在前面
if (i < j) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
i++;
}
//从头部开始扫描
while (i < j && values[i] <= values[j]) i++;
//交换,将较大的记录放到后面
if (i < j) {
int temp = values[i];
values[i] = values[j];
values[j] = temp;
j--;
}
}
//返回轴值的位置
return i;
}
}
5. 算法分析
- 最好情况下,每次划分对一个轴值记录定位后,该轴值的左侧子序列和右侧子序列的长度相同,该情况下时间复杂度为
- 最坏情况下,待排序记录序列刚好是正序或逆序,每次划分只得到一个比上一次划分少一个记录的子序列(另一个子序列为空),最坏情况下的快速排序相当于插入排序,该情况下时间复杂度为
- 因此,平均时间复杂度为