快速排序之重复元素过多的改进

快速排序快的一点毛病没有(重新贴一下代码):

def qsort(arr,lo,hi):
    if hi-lo<=1:
        return
    pivot=arr[lo]
    i,j=lo+1,hi-1
    while True:
        while i<hi and arr[i]<=pivot:
            i+=1
        while j>lo and arr[j]>=pivot :
            j-=1
        if i>=j:
            break
        arr[i], arr[j] = arr[j], arr[i]
    arr[lo], arr[j] = arr[j], arr[lo]
    qsort(arr,lo,j)
    qsort(arr,j+1,hi)

可是比如我是序列[1,-1,0,0,1,1,0,1,2,4,2,1,2]呢?

哦好吧,我就开始交换,交换完了是[-1, 0, 0, 0, 1, 1, 1, 1, 2, 4, 2, 1, 2]

其中枢纽元是1,最前面这个1被放到了绝对正确的位置——不用再排他了。

可是原来这个序列里好多1啊,这些我都不想排了怎么办。

那么针对这个问题,《算法》一书提到了非常好的解决办法:三相切割快速排序。

原来是二路切割,也就是分为比pivot大,或者小于等于pivot的。

这回多了个等于pivot了。

所以至少需要两个额外指针用来交换,然后递归时直接把小于,大于pivot的序列送入递归函数。

代码如下:

def qsort3(arr,lo,hi):
    if hi-lo<=1:
        return
    pivot=arr[lo]
    i,j,k=lo+1,hi-1,lo
    while True:
        if arr[i]<pivot:
            arr[i],arr[k]=arr[k],arr[i]
            i+=1
            k+=1
        elif arr[i]>pivot:
            arr[j],arr[i]=arr[i],arr[j]
            j-=1
        else:
            i+=1
        if i>j:
            break

    qsort3(arr,lo,k)
    qsort3(arr,j+1,hi)

我们看到了j,k分别是大于、小于pivot的边界指针,用于交换(python的交换很简洁)后,再作为新的lo,hi进入递归。

这样有效地减小了子问题大小(至少等于pivot的那一段是不用排序了)。

感谢sdgewick。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值