代码如下
public void quickSort(int[] nums){
// high从length-1开始,否则nums[high]超出范围
quickSort(nums, 0, nums.length - 1);
}
public void quickSort(int[] nums, int low, int high){
if (low >= high)
return;
// 记录左右初始指针
int left = low;
int right = high;
// 记录锚点,选择数组第一位
int pivot = nums[left];
// 保证左右指针相遇即停止
while (left < right){
// 由于这里要不断移动指针,也要进行判断
while (left < right){
// 先从数组右侧查找,按照快排思想,比锚点大的都应该在锚点右侧,因此判断右侧开始大于等于锚点的直接跳过
if (nums[right] >= pivot){
right--;
}else {
// 如果比锚点小,说明应该在锚点左侧,直接把当前right值赋给left处,
// 由于首次开始时left上的值已经保存在pivot中,不用担心覆盖导致丢失
nums[left] = nums[right];
break;
}
}
while (left < right){
// 右侧经过一次变换后,开始从左侧找有没有比锚点大的值,有就赋给right所在的位置
if (nums[left] <= pivot){
left++;
}else {
nums[right] = nums[left];
break;
}
}
}
// 左右指针相遇的时候跳出循环,此时left和right重合的位置就应该是锚点pivot所在的位置
int pivotIndex = left;
nums[left] = pivot;
// 把数组依据锚点分成左右两个子数组,进入quickSort做递归,直到左右子数组元素为1或0跳出
// 左子数组
quickSort(nums, low, pivotIndex - 1);
// 右子数组
quickSort(nums, pivotIndex + 1, high);
}
平均时间复杂度:O(NlgN)
最优时间复杂度:O(NlgN)
最差时间复杂度:O(N^2)
空间复杂度:O(lgN)
稳定性:不稳定
上面的算法可能在极端情况下(数组已经有序)退化成O(N^2)的算法
下面的方式随机在数组中选择一个数作为partition,不会让算法退化
/**
* @Description:
* 快速排序3.0
* @Author: chong
* @Data: 2021/6/20 3:49 下午
*/
public class QuickSortTemplate_3 {
public void quickSort(int[] nums){
quickSort(nums, 0, nums.length - 1);
}
public void quickSort(int[] nums, int low, int high){
if (low >= high)
return;
// 随机在nums数组中选择一个数,让其和low做交换,保证选到合适的partition
swap(nums, low + (int) (Math.random() * (high - low + 1)), low);
int partition = partition(nums, low, high);
quickSort(nums, low, partition);
quickSort(nums, partition + 1, high);
}
public int partition(int[] nums, int low, int high){
int left = low;
int right = high;
int pivot = nums[left];
while (left < right){
while (left < right){
if (nums[right] >= pivot)
right--;
else {
nums[left] = nums[right];
break;
}
}
while (left < right){
if (nums[left] <= pivot)
left++;
else {
nums[right] = nums[left];
break;
}
}
}
nums[left] = pivot;
return left;
}
private void swap(int[] nums, int a, int b){
int temp = nums[a];
nums[a] = nums[b];
nums[b] = temp;
}
@Test
public void test(){
// int[] nums = {5, 9, 1, -4, 5, 3, 7, 6, 1, 32, 23, 42, 57, 2, -49, 4, 67};
// 这个例子能很好的展示3.0和之前的快排在时间上的差距
int[] nums = new int[10000];
for (int i = 0; i < 10000; i++){
nums[i] = i;
}
quickSort(nums);
System.out.println(Arrays.toString(nums));
}
}
其中已经排好序的0-9999的数组采用快速排序算法,之前的算法时间在40-60ms左右,改进后在20-30ms左右。