• 快速排序算法进阶


    改进版本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
    
  • 相关阅读:
    2019.6.1 模拟赛——[ 费用流 ][ 数位DP ][ 计算几何 ]
    LOJ 2721 「NOI2018」屠龙勇士——扩展中国剩余定理
    AGC033 D~F——[ 值放到角标的DP ][ 思路+DP ][ 思路 ]
    LOJ 2719 「NOI2018」冒泡排序——模型转化
    LOJ 3094 「BJOI2019」删数——角标偏移的线段树
    CF 717A Festival Organization——斯特林数+递推求通项+扩域
    LOJ 3090 「BJOI2019」勘破神机——斯特林数+递推式求通项+扩域
    洛谷 4723 【模板】线性递推——常系数线性齐次递推
    bzoj 3924 幻想乡战略游戏 —— 动态点分治
    计算几何整理
  • 原文地址:https://www.cnblogs.com/wisteria68/p/13667235.html
Copyright © 2020-2023  润新知