1、简介:
快排由C.A.R.Hoare在1960年提出,是八大排序算法1中最常用的经典排序算法之一。核心算法思想是分而治之。在Java标准库中 Arrays 类的 sort 方法里面的源码使用了优化后的快速排序。
2、快速排序的基本思想:
- 1)选定Pivot中心轴
- 2)将大于Pivot的数字放在Pivot的右边
- 3)将小于Pivot的数字放在Pivot的左边
- 4)分别对左右子序列重复前三步操作
3、时间复杂度
平均时间复杂度为O(n logn),Worst Case的时间复杂度为O(n^2)。2
时间复杂度的推导见:
https://www.cnblogs.com/HDK2016/p/6876313.html
4、代码
import java.util.Random;
public class Solution {
// 快速排序 1:基本快速排序
/**
* 列表大小等于或小于该大小,将优先于 quickSort 使用插入排序
*/
private static final int INSERTION_SORT_THRESHOLD = 7;
private static final Random RANDOM = new Random();
public int[] sortArray(int[] nums) {
int len = nums.length;
quickSort(nums, 0, len - 1);
return nums;
}
private void quickSort(int[] nums, int left, int right) {
// 小区间使用插入排序
if (right - left <= INSERTION_SORT_THRESHOLD) {
insertionSort(nums, left, right);
return;
}
int pIndex = partition(nums, left, right);
quickSort(nums, left, pIndex - 1);
quickSort(nums, pIndex + 1, right);
}
/**
* 对数组 nums 的子区间 [left, right] 使用插入排序
*
* @param nums 给定数组
* @param left 左边界,能取到
* @param right 右边界,能取到
*/
private void insertionSort(int[] nums, int left, int right) {
for (int i = left + 1; i <= right; i++) {
int temp = nums[i];
int j = i;
while (j > left && nums[j - 1] > temp) {
nums[j] = nums[j - 1];
j--;
}
nums[j] = temp;
}
}
private int partition(int[] nums, int left, int right) {
int randomIndex = RANDOM.nextInt(right - left + 1) + left;
swap(nums, left, randomIndex);
// 基准值
int pivot = nums[left];
int lt = left;
// 循环不变量:
// all in [left + 1, lt] < pivot
// all in [lt + 1, i) >= pivot
for (int i = left + 1; i <= right; i++) {
if (nums[i] < pivot) {
lt++;
swap(nums, i, lt);
}
}
swap(nums, left, lt);
return lt;
}
private void swap(int[] nums, int index1, int index2) {
int temp = nums[index1];
nums[index1] = nums[index2];
nums[index2] = temp;
}
}
参考: