执行流程
- 从序列中选择一个轴点,可以每次选择
index=0位置的元素 - 利用轴点元素,将序列分割成
2个子序列,将小于轴点的元素放在轴点左侧,将大于轴点的元素放在轴点右侧,等于轴点的元素放哪边都可以 - 对子序列执行1,2操作,直到子序列只有一个元素为止
快速排序的本质:逐渐把每个元素都转换成轴点元素
轴点元素的构造
接下来的一个问题是,我们怎么找到轴点元素,看图
代码
public class QuickSort {
public static void main(String[] args) {
int[] array = {9, 5, 3, 2, 7, 6, 1};
QuickSort quickSort = new QuickSort(array);
quickSort.sort();
Arrays.stream(array).forEach(System.out::println);
}
private int[] array;
public QuickSort(int[] array) {
this.array = array;
}
/**
* 排序
*/
public void sort() {
sort(0, array.length);
}
/**
* 对[begin,end)范围内的元素进行排序
*/
private void sort(int begin, int end) {
//子序列必须大于2个元素,才能进行排序
if (end - begin < 2) {
return;
}
//确定轴点位置
int mid = pivotIndex(begin, end);
//对轴点左侧子序列进行快速排序
sort(begin, mid);
//对轴点右侧子序列进行快速排序
sort(mid + 1, end);
}
/**
* 确定[begin,end)之间的轴点元素位置
*/
private int pivotIndex(int begin, int end) {
//默认取第一个元素为轴点元素
//备份轴点元素
int pivotValue = array[begin];
//从end位置开始遍历
end--;
while (begin < end) {
while (begin < end) {
//如果end位置元素>轴点元素
if (pivotValue < array[end]) {
end--;
}
//end位置元素<=轴点元素
else {
array[begin] = array[end];
begin++;
break;
}
}
while (begin < end) {
//如果轴点元素>begin位置的元素
if (pivotValue > array[begin]) {
begin++;
}
//轴点元素<=begin位置的元素
else {
array[end] = array[begin];
end--;
break;
}
}
//用轴点元素替换最后的位置
array[begin] = pivotValue;
}
return begin;
}
}
总结:快速排序平均时间复杂度O(nlogn),空间复杂度为O(logn),快速排序在左右子序列极度不平衡的情况下,时间复杂度会退变成O(n2),为了避免出现这样的情况,我们在开始选择轴点元素时可以随机选择一个元素,而不是每次都选择第一个元素.