快速排序-总结与改进

本文详细介绍了快速排序的基本原理,并探讨了如何将其转换为非递归形式,以及如何从前端获取值进行排序。文章重点在于三个改进点:处理相同数值的优化,通过随机选择划分元素提升效率,以及针对小规模子数组使用插入排序的策略,以减少平均时间复杂度。
摘要由CSDN通过智能技术生成

之前的几次面试都有问到快速排序,我的写法都是按照算法导论上随便写写的:

一:基本快速排序:(参照算法导论)

#快速排序
def quicksort(nums,p,r):
    if p<r:
        q=partition(nums,p,r)
        quicksort(nums,p,q-1)
        quicksort(nums,q+1,r)
    return

def partition(nums,p,r):
    x=nums[r]
    i=p-1  #记录位置
    for j in range(p,r):
         if nums[j]<=x:
             i+=1
             nums[i],nums[j]=nums[j],nums[i]
    nums[i+1], nums[r] = nums[r], nums[i+1]
    return i+1

二:偶尔会问怎么改成非递归的

def quicksort2(nums,p,r):
    #非递归实现,只需要申请一个 栈来记录 需要排序的起始位置与终点位置
    stack=[p,r]
    while stack:
        new_r=stack.pop()
        new_p=stack.pop()
        q=partition(nums,new_p,new_r)
        if new_p<q-1:
            stack.extend([new_p,q-1])
        if new_r>q+1:
            stack.extend([q+1,new_r])
    return nums

三:写成一个函数

def quicksort(nums,p,r):
    if p>=r:return
    x=nums[r]
    i=p-1  #记录位置
    for j in range(p,r):
         if nums[j]<=x:
             i+=1
             nums[i],nums[j]=nums[j],nums[i]
    nums[i+1], nums[r] = nums[r], nums[i+1]
    q=i+1
    quicksort(nums,p,q-1)
    quicksort(nums,q+1,r)
    return

四:如果从前端取值:

def quicksort(nums,p,r):
    if p>=r:return
    x=nums[p]
    i=p  #记录位置
    for j in range(p+1,r+1):
         if nums[j]<x:
             i+=1
             nums[i],nums[j]=nums[j],nums[i]
    #最后的结果:nums[p+1,,,,i-1]都小于x;nums[i,...,r]>=x
    nums[i], nums[p] = nums[p], nums[i]
    quicksort(nums,p,i-1)
    quicksort(nums,i+1,r)
    return

五:改进一:

考虑极端的情况:如果n个数都相同,插入排序是O(n),而快排则变成了平方级别的。
考虑从两端划分:
i从左往右扫,j从右往左扫;
如果i>=j循环终止
否则交换i,j对应的值(这里相当于又找到了一个大于等于key和一个小于等于key的数,i++,j–)
(python没有do while 写成这个会比较简单)

def quicksort(nums,p,r):
    if p>=r:
        return
    key=nums[p]
    i=p+1  #从左往右
    j=r #从右往左
    while True:
        while i<=r and nums[i]<key:
            i+=1
        while nums[j]>key:
            j-=1
        if i>=j:
            break
            #此时nums[p+1,,,i-1]都小,注意i可能为r+1
            #nums[j+1,r]都大
        nums[i],nums[j]=nums[j],nums[i]
        i+=1
        j-=1
    nums[p],nums[j]=nums[j],nums[p]
    quicksort(nums,p,i-1)
    quicksort(nums,j+1,r)
    return

六:改进二:

如果对于排序好的数,选取第一个元素做划分会导致效率的降低(平方级别)。
所以应该选择随机选择划分元素.
在 if的后面加上:

    x=random.randint(p,r)
    nums[x],nums[p]=nums[p],nums[x]

七:改进三:

修改 if
快速排序花费了大量的时间来排序很小的子数组,如果采用插入排序会更快
可以修改为:

    if p-r<cutoff:
        return

其中,cutoff是一个小整数,然后选择其他排序算法进行排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值