zoukankan      html  css  js  c++  java
  • 希尔排序、计数排序、桶排序、基数排序

    希尔排序

    希尔排序思路:

    • 希尔排序是一种分组插入排序算法。
    • 首先取一个整数d1=n/2, 将元素分为d1个组, 每组相邻量元素之间距离为d1,在各组内进行直接插入排序
    • 取第二个整数d2=d1/2, 重复上述分组排序过程,直到di=1,即所有元素在同一组内进行直接插入排序
    • 希尔排序每趟并不使某些元素有序,而是使整体数据越来越接近有序;最后一趟排序是的所有数据有序。

    复习一下插入排序:

    def insert_sort(li):
    
        for i in range(1, len(li)):
            j = i - 1   # j 为手里最大的牌
         tmp = li[i]
            while j >= 0 and li[j] > tmp:     # 只要手里最大的牌比摸回来的牌大就一致往右移动
                # j >= 0 ,说明所有数都比摸到的牌要大,直接退出循环
                li[j+1] = li[j]     # 右移
                j -= 1
    
            li[j+1] = tmp     # 确定要插入的时候,是必须插到j的前一个位置

    再看实现希尔排序代码:

    def insert_sort(li, gap):
    
        for i in range(gap, len(li)):
            j = i - gap
            tmp = li[i]    # 摸回来的牌的值
    
            while j >= 0 and li[j] > tmp:
                # 在有序区里面,摸回来的牌比有序区的牌(从右到左)的值小,有序区的牌就向右移动一个位置
                li[j+gap] = li[j]
                j -= gap
    
            li[j+gap] = tmp
    
    
    def shell_sort(li):
    
        d = len(li) // 2
        while d >= 1:
            insert_sort(li, d)
            d = d // 2
    
    
    li = list(range(1000))
    import random
    random.shuffle(li)
    shell_sort(li)
    print(li)

    希尔排序小结:

      希尔排序的时间复杂度比较复杂,且和选区的grap序列有关。

    计数排序

    现在有一个列表,已知列表中的数范围都在0到100之间。设计算法在O(n)时间复杂度内将列表进行排序。

    思路:

    创建一个列表,用来统计每个数出现的次数。(index存数字大小,value存出现次数)

    def count_sort(li, max_num):
        # 创建一个max_num长的列表
        count = [0 for i in range(max_num + 1)]
    
        for num in li:
            count[num] += 1
    
        li.clear()
        for ind, val in enumerate(count):
            for i in range(val):
                li.append(ind)
    
    import random
    li = [random.randint(0,100) for _ in range(1000)]
    count_sort(li, len(li))
    print(li)

    计数排序的缺点:

    如果列表只有5个数,数字范围是1到1亿,就需要开一个一亿长度的列表,严重浪费空间和资源不合理使用。

    桶排序

    在计数排序中,如果元素的范围比较大(比如在1到1亿之间), 如何改造算法?

    桶排序(Bucket Sort):首先将元素分在不同的桶中,再对每个桶中元素排序。

    • 桶排序的表现取决于数据的分布。也就是需要对不同数据排序时采取不同的分桶策略。
    • 平均情况时间复杂度:O(n+k)
    • 最坏情况时间复杂度:O(n2k)
    • 空间复杂度:O(nk)
    def bucket_sort(li, n=100, max_num=10000):
        buckets = [[] for i in range(n)]    # 创建通
        for var in li:
            i = min(var//(max_num//n), n-1)     # i表示var放到几号桶里
            buckets[i].append(var)      # 把var加到桶里
    
            # 保持桶内的顺序
            for j in range(len(buckets[i])-1, 0, -1):
                if buckets[i][j] < buckets[i][j-1]:     # 必须是升序   降序的话[9,8,7,6] [99,87,55,22], 合并之后并不是有序
                    buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]
                else:
                    break
        sorted_li = []
        for buc in buckets:
            sorted_li.extend(buc)
        return sorted_li
    
    import random
    
    li = [random.randint(0,99999) for i in range(100)]
    li = bucket_sort(li)
    print(li)

    基数排序

    基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。

     

    def radix_sort(li):
        max_num = max(li) # 最大值 9->1, 99->2, 888->3, 10000->5
        it = 0
        while 10 ** it <= max_num:
            buckets = [[] for _ in range(10)]
            for var in li:
                # 987 it=1  987//10->98 98%10->8;    it=2  987//100->9 9%10=9
                digit = (var // 10 ** it) % 10
                buckets[digit].append(var)
            # 分桶完成
            li.clear()
            for buc in buckets:
                li.extend(buc)
            # 把数重新写回li
            it += 1
  • 相关阅读:
    window7访问虚拟机ubuntu中的mysql
    photo sphere viewer使用图像数据替代路径来生成全景图
    pgmagick,pil不保存图片并且获取图片二进制数据记录
    flask_admin model官方文档学习
    python pip更换下载源(转)
    flask admin学习记录
    mongodb权限管理(转)
    vmware三种网络连接模式区别
    使用VLC推送TS流(纯图版)
    【转】RTMP/RTP/RTSP/RTCP协议对比与区别介绍
  • 原文地址:https://www.cnblogs.com/Xuuuuuu/p/10821568.html
Copyright © 2011-2022 走看看