zoukankan      html  css  js  c++  java
  • 计数排序-桶排序-基数排序

    计数排序

       计数排序的实现主要是数据样本的特殊性(正整数,明确最大边界)和利用列表索引位置来记录值,索引值来统计个数

      最后循环索引,根据值(个数)确定添加多少个

    import time
    
    def cal_time(func):
        def wrapper(*args, **kwargs):
            t1 = time.time()
            result = func(*args, **kwargs)
            t2 = time.time()
            print("%s running time: %s secs." % (func.__name__, t2 - t1))
            return result
    
        return wrapper
    
    
    @cal_time
    def count_sort(li, max_count=100):
        count = [0 for _ in range(max_count+1)]
        for val in li:
            count[val] += 1
        li.clear()
        for ind, val in enumerate(count):
            for i in range(val):
                li.append(ind)
    
    @cal_time
    def sys_sort(li):
        li.sort()
    
    import random, copy
    li = [random.randint(0,100) for _ in range(100000)]
    
    li1 = copy.deepcopy(li)
    li2 = copy.deepcopy(li)
    
    count_sort(li1)
    sys_sort(li2)
    

    桶排序

       桶排序实现思路和计数排序实现思路大体相同,计数排序是通过列表索引来把相同的数弄到一组,而桶排序则是确定一个范围来确定分组

      代码实现思路:

    • 根据桶数和最大数确定放入哪个桶
    • 桶内进行冒泡排序
    import random
    
    
    def bucket_sort(li, n=100, max_num=10000):
        buckets = [[] for _ 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]:
                    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
    
    
    li = [random.randint(0,10000) for i in range(100000)]
    # print(li)
    li = bucket_sort(li)
    print(li)
    

      桶排序不是一种特别理想的排序,如果数据分布不均匀,过多的数落入到一两桶里,排序效果就跟冒泡排序没有多大差别

    基数排序

      基数排序实现思路是多关键词排序和桶排序的结合,多关键词排序,举个例子,你就明白了,比如先工资排序,如果相同的再按年龄排序

      基数排序实现过程:

    • 先对个位进行排序,个数为相同的放同一个桶,合并桶
    • 在对合并桶数据的十位排序,十位相同放一个桶中,合并桶
    • 循环上述过程,个十百千万...

      代码实现要点:获取最大数确定循环位数,每次循环桶数确定0-9,分桶合并桶

    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
    

       基数排序在某些情况下,比快速排序还快,是一种比较理想的排序,算法复杂度接近O(kn),它运算快慢更多取决于列表中数字大小,如果很大,它就会慢下来,而快排则是取决于列表长度,所以要根据不同场景来使用这个两个算法

  • 相关阅读:
    vim的强大,vim设置和插件的使用,脱离windows才是王道
    [VS2013]如何闪开安装VS2013必须要有安装IE10的限制
    常用客户端实现逻辑
    开源控件ViewPagerIndicator学习
    常用设计模式
    主题演讲:未来新趋势电动车
    你最美好的年华
    一度总结
    android线程池ThreadPoolExecutor的理解
    Touch事件or手机卫士面试题整理回答(二)
  • 原文地址:https://www.cnblogs.com/xinsiwei18/p/10140745.html
Copyright © 2011-2022 走看看