前段时间,我以前大学的一个学长去面试的时候,就问到了快速排序,并要求手写出来,那么,如果问到你,能不能在手纸上,呸!。。。在纸上写出来呢?
java的快速排序是面试经常要考到的哟!本文章接下来会深入浅出让大家能够了解快速排序,并能够知道快速排序的原理哦~
1,什么是快速排序?
让我们先来了解一下什么是快速排序,快速排序也叫快排,是冒泡排序的升级版,其效率要远高于冒泡排序,是一种高级的排序方式
它采用分而治之的思想,来完成排序
2,快速排序的思想
这里先了解一下即可,后面会有图解
采用分而治之的思想
1. 随便选一个数作为中轴点,将数组以中轴点作为分界线,分为左右两部分,
2. 以从小到大的排序为例,左边部分的值都要小于右边的值
(换而言之,就是左边部分都小于中轴点的值,右边部分都大于中轴点的值)
3. 左右两部分能够再分就继续分(待分的部分长度大于1),
重复这个操作,直到数组不可再分为止,到这里我们的排序就已然完成
让我们看一下图解:
所有算法都是思想最重要,如果你看懂了思想的话,就请继续往下看,else-》请就着图解,仔细阅读思想,把思想看懂再看代码!!!
3,代码实现
public static void main(String[] args) {
int[] arr={14,4,1,5,2,6,17};
quickSort(arr);//测试快速排序
System.out.println("Arrays.toString(arr) = " + Arrays.toString(arr));
}
/*快速排序*/
private static void quickSort(int[] arr) {
group(arr,0,arr.length-1);
}
/**
* 快速排序的分组方法【就是通过中轴值(随意从待排序的数组中选一个值,
* 为了方便,我直接选左边第一个)
* @param arr 数组
* @param lo (low的简写)待排序部分最左边的值的下标
* @param hi (high的简写)待排序部分最右边的值的下标
*/
private static void group(int[] arr, int lo, int hi) {
//安全验证
if(lo>=hi)
return;
//通过快速排序的核心方法获取中心点
//【虽然我们这里是选待排序数组的左边第一个(即lo),
//但是经过核心方法之后,中轴的位置已然改变,
//所以不能直接用lo这个下标】
int pivot = core(arr,lo,hi);
//这里递归调用分组的方法【表示分组完成后继续分组】
group(arr,lo,pivot-1);
group(arr,pivot+1,hi);
}
/**
* 快速排序的核心方法【实际上就是双指针算法
* (不要看到算法就觉得困难哦,
* 这个十分简单!哈哈~下面会为大家注释好,放心观看)】
* @param arr 数组【这个数组实际用到的部分就是lo-hi的部分】
* @param lo (low的简写)待排序部分最左边的值的下标
* @param hi (high的简写)待排序部分最右边的值的下标
* @return 分好左右两边后,中轴所在位置的下标
*/
private static int core(int[] arr, int lo, int hi) {
int pivot=lo;//中轴的位置,我们选左边第一个
//定义左右指针(就是int类型的变量)
int left=lo,right=hi;
//指针指向待排序数组的左右两端,从右边开始遍历,找到一个比中轴小的,
//然后从左边找遍历到一个大的,交换两者的位置
while(left<right){
while(left<right&&arr[right]>=arr[pivot]) right--;
while(left<right&&arr[left]<=arr[pivot]) left++;
//交换左右值的位置
change(arr, left, right);
}
//经过循环后,左右指针已经重合在一起,我们交换中轴与左指针元素的位置
//【为什么重合在一起了?请看第一个while的条件】
change(arr,pivot,left);//这里还可以稍微简化,不过效果差不多
return left;
//因为中轴值和左指针元素交换了位置,所以返回左指针元素
}
/**
* 交换两个数在数组中的位置
* @param arr
* @param left
* @param right
*/
private static void change(int[] arr, int left, int right) {
int temp=arr[left];
arr[left]=arr[right];
arr[right]=temp;
}
说明:不要被长篇幅吓到哦,基本上都是注释,代码很少
4,时间复杂度和稳定性
平均时间复杂度:O(nlogn)
最差时间复杂度:O(n^2)
稳定性:不稳定的排序【排完序后两个相等的元素没有交换位置就是稳定的排序】
时间复杂度是衡量算法效率的东西,如果想要清楚地了解,欢迎在评论区留言,那么我下期就会出一期关于时间复杂度的专栏讲解
5,与冒泡排序花费的时间比较
排序一百万条数据,
快速排序花费时间:170ms
冒泡排序花费时间:等了好几分钟都不出结果
申明:不同的设备,花费的时间可能有些不同哦!
结论:完败冒泡
看在我这么用心的份上,动动你的小手帮我点个赞吧,这会让作者更加有动力为你们写文章哦,谢谢啦~