快速排序算法进阶

改进版本1

  舍去一边的快速排序,该边的快速排序用自身的排序代替。

def quick2(li,left,right):
    while left<right:
        mid=partition2(li,left,right)#索引的中间值
        quick2(li,left,mid-1)#单边递归法
        left=mid+1
    return li

def partition2(li,left,right):
    pivot=li[left]#定位左边的元素
    while left<right:#还没有搜索完
        # 从右边开始,将大于中间索引所在元素的元素放在左边
        while left<right and pivot<li[right]:
            right-=1
        li[left]=li[right]#在左边加
        # 从左边开始,将小于中间索引所在元素的元素放在右边
        while left<right and pivot>li[left]:
            left+=1
        li[right]=li[left]#在右边加
    li[left]=pivot#将右边的的最左端赋值为中间值
    return left#返回中间值的索引

改进版本2

  将有监督的快速排序优化为无监督的快速排序。

def quick3(li,left,right):
    while left<right:
        mid,right1 =partition3(li,left,right)#索引的中间值
        quick3(li,left,right1)
        left=mid
    return li

def partition3(li,left,right):
    pivot=li[left]#定位左边的元素
    while left<=right:
        while pivot<li[right]:
            right-=1
        while pivot>li[left]:
            left+=1
        if(left<=right):
            li[left],li[right]=li[right],li[left]#在右边加
            left += 1
            right -= 1
    return (left,right)#返回中间值的索引

改进版本3

  在分割点选取的初始值方面进行优化,在待分割下标区间随机选取分割点下标。

def quick4(li,left,right):
    while left<right:
        mid,right1 =partition4(li,left,right)#索引的中间值
        quick4(li,left,right1)
        left=mid
    return li

def partition4(li,left,right):
    pivot=li[int(left+np.random.rand()%(right-left+1))]#随机取原始分割点
    while left<=right:
        while pivot<li[right]:
            right-=1
        while pivot>li[left]:
            left+=1
        if(left<=right):
            li[left],li[right]=li[right],li[left]#在右边加
            left += 1
            right -= 1
    return (left,right)#返回中间值的索引

改进版本4

  继续在分割点选取的初始值方面进行优化,在待分割区间使用三点取中法选取初始分割点。

def quick5(li,left,right):
    while left<right:
        mid,right1 =partition5(li,left,right)#索引的中间值
        quick5(li,left,right1)
        left=mid
    return li

def partition5(li,left,right):
    pivot=mid_num(li,left,right)#三点取中法确定原始分割点
    while left<=right:
        while pivot<li[right]:
            right-=1
        while pivot>li[left]:
            left+=1
        if(left<=right):
            li[left],li[right]=li[right],li[left]
            left += 1
            right -= 1
    return (left,right)#返回中间值的索引
def mid_num(li,left,right):
    a=li[left]
    b=li[right]
    c=li[int((left+right)/2)]
    if(a>b):
        a,b = b,a
    if(a>c):
        a,c = c,a
    if (b > c):
        b,c = c,b
    return b
posted @ 2020-09-14 15:59  紫藤花下酒馆  阅读(195)  评论(0编辑  收藏  举报