快速排序-总结与改进

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

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

#快速排序
def quicksort(nums,p,r):
    if p1)
        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_p1:
            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]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]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是一个小整数,然后选择其他排序算法进行排序。

你可能感兴趣的:(数据结构与算法)