Java排序系列之快速排序

前言:
排序算法之快速排序

简介:
最开始看见这个名字,就在想,名字这么嚣张,快排,那必然是时间复杂度领先其它排序算法咯!后面发现,是的,它确实快!快排呢,是对冒泡排序的一种改进,它是通过多次比较和交换来实现的。简单的描述一下它的运行过程就是,先选定一个数,把小于这个数的其他数放到被选定这个数的左边,大于这个数的其他数放到该数的右边,那么就形成该数左边的序列全部小于该数右边的序列。好了,那么我们对左边的序列和右边的序列重复以上的过程,直到整个数组有序。听着很简单是吧,但是实现呢,确实要比冒泡排序复杂那么一丢丢,不过快排效率高于冒泡排序,为了这一点多写点代码也是值得的。

原理:
1)首先选定一个分界值,一般情况我们选择待排序数组的第一个值作为分界值,当然你也可以选择其他的。

2)将小于分界值的数据全部放到数组左边,将大于等于分界值的数据全部放到数组右边。此时,左边的数据都小于边界值,右边的数据都大于等于边界值,且左边的数据全部小于右边数据。

3)针对左边和右边的子序列,重复1)、2)步骤,直到整个数组有序。

从上面的原理我们可以看出,这其实是一个递归的定义,接下来用一张图帮大家理解一下这个过程:
在这里插入图片描述
这个图是百度的哈,不是自己画的(偷懒了!)。其实算法的思想还是挺简洁明了的,接下来咱们用Java实现这个算法:

void quickSort(int[] arr,int start,int end){
    int num = arr[start];//分界值的选取
    int left = start,right = end;//数组第一个元素和最后一个元素的下标
    while(left < right){
    	//跳过右边大于分界值的数
        while ((left < right) && arr[right] > num ){
            right--;
        }
        //跳过左边小于分界值的数
        while((left < right) && arr[left] < num){
            left++;
        }
        //这里是处理左边等于右边同时又等于num的时候,将该数划给左边,当然你也可以划给右边
        if(arr[left] == arr[right] && (left < right)){
            left++;
        }else{
        	//元素交换
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }
    }
    //下面两个if,分别对左子序列和右子序列进行快排
    if(left - 1 > start) {
    	quickSort(arr,start,left - 1);
    }
    if(right + 1 < end){
    	quickSort(arr,right + 1,end);
    }
    return;
}

接下来咱们再来讨论下这个算法,看看该算法的时间复杂度如何?

快排一次是从两头交替搜索,直到left和right重合,因此时间复杂度为O(n),然而这只是一趟快排所消耗的时间,整个算法消耗的时间还要看划分的情况。

最理想的情况,每次选择的值基本上选择到了中值(该中值指的是这个值基本上把数组平分成了元素数量相等的两份),那么要经过log2n趟的划分,便可得到长度为1的数组,此时排序完成,整个算法的时间复杂度为O(nlog2n)。最坏的情况,每次选择都选到了最大或者最小的元素,那么需要经过n次划分,所以时间复杂度为O(n^2)。

当然了,为了改善最坏情况下的性能,我们希望每次取值都尽可能的靠中间,因此,对该算法的一个改进举措为-----“三者取中法”,即从arr[left]、arr[right]、arr[(left + right) / 2]三个值中选择中间的值作为划分值(这个比较简单,就不贴代码了)。经过证明,快排的平均时间复杂度为O(nlog2n)。所以说该算法还是担得起快排这个称呼的。

从空间性能上来看呢,快排需要用栈空间来实现递归,在最优的情况下,所需要的栈的深度为log2n,最坏的情况下栈的深度为n。即在最好的情况下空间复杂度为O(log2n),最坏的情况下空间复杂度为O(n)。

哦对,忘记讨论稳定性了,其实哈,明白了算法原理,我们也就知道了,快排显然是不稳定的排序算法,它不能保证相等元素的相对位置。

总结:
快排是使用递归实现的,最好情况下时间复杂度为O(nlog2n),空间复杂度为O(log2n);最坏情况下时间复杂度为O(n^2),空间复杂度为O(n);平均时间复杂度为O(nlog2n)(平均时间复杂度为什么就是O(nlog2n)呢?以后再写博客研究了);同时呢,快排不是稳定的排序算法。

好了,快排就讲到这里,接下来会对其它的排序算法持续更新。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值