前言
今天我们来看快速排序如何实现 下面注释非常的详细 我一般这种性质的知识点 一般都是以注释为解释了 ~~ 仔细查阅吧 在面试中快速排序经常被问到
代码
package top.liwenxiang.ms;
import java.util.Arrays;
import java.util.Random;
public class 快排 {
public static void main(String[] args) {
// 快速排序 效率比较高 相对来说比较难理解
// 实现思路
// 首先有 5 2 1 3 5 4 9 6 0 1 这样一个数组
// 我们第一步是需要找出一个基准值 可以是数组的开头第一个 也可以是 数组的结尾第一个
// 如果我们选择的是开头的第一个
// 我们就需要先从右边开始遍历查找比基准值小的 找到小的之后在开始从左边遍历找比基准值大的 找到之后 交换改两个元素的位置
// 然后继续从右边遍历查找比基准值小的 左边查找比基准值大的 等到左边索引位置和右边索引位置相遇的时候 停止遍历 将基准值和 相遇位置的
// 值进行交换 一次遍历之后 就找出了 所有比基准值小的值 和比基准值大的值 其次就是重复对小的数组 和 大的数组 进行再次遍历 重复循环
// 可以使用递归的形式实现
// 我们的左边索引是不能够大于右边索引的 如果大于的话就应该直接return结束方法的执行了
int[] quickSortArr = {5,2,1,3,5,4,9,6,0,1};
// 手动推比过程 5 2 1 3 5 4 9 6 0 1
// 我们采用5作为基准数
// 第一轮 第一步中的第一小步 先从右边查找比5小的数 1 小于5 结束右侧查找
// 5 2 1 3 5 4 9 6 0 1
// 第一轮 第一步中的第二小步 从左边查找比5大的数 9 大于 5 结束左侧查找
// 第一轮 第一步中的第三小步 交换位置 1 和 9 的位置
// 第一轮 结果是
// 5 2 1 3 5 4 1 6 0 9
// 第二轮
// 5 2 1 3 5 4 1 6 0 9
// 第二轮 第一步第一小步 此时 left 在下标6的位置 1 right 在下标9 的位置 9
// 第二轮 第一步第二小步 继续进行右侧向左侧移动查询比基准数小的数 0 比 5 小 结束右侧遍历
// 第二轮 第一步第三小步 继续进行左侧向左侧移动查询比基准数大的数 6 比 5 大 结束左侧遍历
// 第二轮 第一步第四小步 继续进行左侧向左侧移动查询比基准数大的数 6 比 5 大 结束左侧遍历
// 第二轮 第一步第五小步 交换位置 5 2 1 3 5 4 1 0 6 9
// 第三轮
// 5 2 1 3 5 4 1 0 6 9
// 第三轮 第一步第一小步 此时 left 在下标 7 的位置 1 right的位置下标 8 的位置 6
// 第三轮 第一步第二小步 继续进行右侧向左侧移动查询比基准数小的数 继续左侧遍历 发现left和right碰面了结束遍历
// 将碰面的位置的元素和基准数替换位置
// 结果 0 2 1 3 5 4 1 5 6 9
// 重复循环的条件就是 对左侧 和 右侧的元素再次进行遍历匹配
// QuickSort(int[] arr,int left,int right) 数组 左侧开始下标 结束遍历的位置 通常是传入数组的长度减1
// QuickSort(arr,left,j-1)
// QuickSort(arr,i+1,right)
int[] iii = new int[100000];
for (int i = 0 ; i < iii.length ; i++){
iii[i] = new Random().nextInt(100000);
}
long start = System.currentTimeMillis();
quickSort(iii,0,iii.length - 1);
long end = System.currentTimeMillis();
System.out.println(Arrays.toString(iii));
System.out.println(end - start + "ms");
}
// 快速排序
// 参数解释 需要排序的数组 左侧开始遍历位置 遍历到哪里的位置
public static void quickSort(int[] arr,int left,int right){
// 如果左侧索引位置大于右侧的索引位置就应该退出了
if (left > right) return;
// 选取基准数 就是arr[0]
int base = arr[left];
// 左边索引位置
int i = left;
// 右边索引位置
int j = right;
// 判断是否i和j相遇 相遇则代表第一轮结束 再循环后就应该交换 基准数和相遇位置的元素
while (i < j){
// 先从右侧开始查找比基准数小的 大的话直接接着循环
while (arr[j] >= base && i < j){
j--;
}
// 从左侧开始查找比基准数大的 小的话直接接着循环
while (arr[i] <= base && i < j){
i++;
}
// 找到对应的元素交换位置 小的在左边 大的在右边
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 交换基准数和相遇位置的元素
arr[left] = arr[i];
// 这里 i 和 j 都可以 因为当前的下标是一样的
arr[i] = base;
// 重新调用自身 对左侧列表进行排序 其实位置还是 left 结束位置是 j - 1 代表的刚好是左侧下于基准数的数组位置大小
quickSort(arr,left,i-1);
// 重新调用自身 对右侧列表进行排序 开始位置是 i + 1 就是 当前 基准数 后面的第一个数开始到 数组的结束位置就是length大小
quickSort(arr,i+1,right);
}
}