数组的Partition与快速排序

本文详细介绍了数组的Partition操作,包括荷兰国旗问题,并探讨了快速排序的不同版本,从无改进到工程上常用的改进方法。文章还分析了快速排序的时间复杂度,指出其在最坏情况下的空间复杂度为O(N),而最佳情况下为O(logN),实际应用中通常收敛于O(logN)。最后,阐述了快速排序在工程上被广泛使用的原因。
摘要由CSDN通过智能技术生成

数组的Partition

在数组中取一个数p,把<=p的数都放在左边,>p的数放在右边,数的排序可以是无序的。
流程:
在a[0]之前建一个<=区,i指向a[0]
若a[i] <= p, a[i]与<=区的右边一个数交换,<=区向右扩一个单位,i++
若a[i] > p, i++
升级:荷兰国旗问题
在数组中取一个数p,把<p的数都放在左边,=p的数放中间,>p的数放在右边,数的排序可以是无序的。
流程:
在a[0]之前建一个<=区,i指向a[0],a[a.length-1]之后建立一个>=区
若a[i] < p, a[i] < p, a[i]与<区后一个数交换,<区向右扩,i++
若a[i] > p,a[i]和>区前一个数交换,>区向左扩,i不变
若a[i] == p,i++

快速排序

快速排序的核心思想便是数组的partition,通过一轮partition之后,可以把一个数插到中间,这样每个数都会找到自己的位置,然后把左边和右边的数组分别递归进行partition,每个数字都可以找到自己的位置,最后数组便是有序的了。

没有任何改进的快排

用数组的最后一个数p作为划分,<=p的放数组的左边,>p的放数组的右边,一轮partition之后,p就存在与数组中间的某个位置,然后p不动,p左边的数组和右边的数组重复以上流程。

稍微改进的快排

用数组的最后一个数p作为划分,把<p的数都放在左边,=p的数放中间,>p的数放在右边,然后=p的区域不动,区域左边的数组和区域右边的数组继续重复以上流程。

进阶改进的快排

每次都随机把l到r上的任意一个数交换到最后,然后用这个数进行partition,最后p落在任意一个位置上的概率都是相等的,即1/n
累加的公式得出来,时间复杂度为O(n*logN),最坏情况和最好情况都已成概率事件了

工程上改进的快排

在quickSort这一步,当l < r - 60 时,使用插入排序。虽然插入排序时间复杂度为O(n^2),但是样本量少的时候速度飞快,没有时间瓶颈。

快速排序的时间复杂度分析

1.最坏O(n^2)
例子 1 2 3 4 5 6 7 8 9
以9作为划分,每次只搞定了最后一个数,每次都要承载O(n)的时间复杂度,所以总的时间复杂度为O(n^2)
2.最好O(n*logN)
每次都把p打到中点位置,左边和右边的长度都为n / 2
得出来的公式:T(N) = 2T(N / 2) + O(N)
其中O(N)为partition的时间复杂度
根据master公式得出时间复杂度为O(n)
由于按最差情况来估计时间复杂度,所以完全不改进的快排时间复杂度为O(n^2)。

空间复杂度

1.最坏情况 O(N)
2.最好情况 O(logN)
结论:经过概率的统计,最后收敛于O(logN)。

快速排序的Code

public class QuickSort_lijunru {
   

    public static void quickSort(int[] arr) {
   
        if (arr == null || arr.length < 1) {
   
            return;
        }
        qui
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值