计数排序-桶排序-基数排序

计数排序

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

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

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),它运算快慢更多取决于列表中数字大小,如果很大,它就会慢下来,而快排则是取决于列表长度,所以要根据不同场景来使用这个两个算法

posted @ 2018-12-18 23:47  财经知识狂魔  阅读(240)  评论(0编辑  收藏  举报