什么是桶排序?

上一篇说了计数排序,一种稳定的排序,时间复杂度是指数级,但是,计数排序不适用于跨度很大或者浮点数,那么有没有可以处理浮点类型的稳定排序呢?桶排序就是。

桶排序的实现

  首先说一下桶排序的桶是什么概念,这里的“桶”是一个区间范围,里面可以承载一个或多个元素。桶排序的第一步就是确定桶的个数和区间。具体的建立多少个桶、每个桶的区间范围是多少,有不同的方式,我们这里使用桶的数量等于原始数列的元素的数量(为什么等于数列的数量,后面会讲到)。除了最后的一个桶只包含最大值,其他的值分散在其他桶里。

区间跨度 = (最大值-最小值)/ (桶的数量 - 1)

第二步是把原始数列的元素放入桶中

第三步是桶内的元素进行排序

第四步就是遍历所有的桶,输出元素

0.5,0.84,2.18,3.25,4.5

  上面是思路,具体代码如下:

def sortBucket(array):
    max = array[0]
    min = array[0]
    for i in array:
        if max < i:
            max = i
        if min > i:
            min = i

    # 1.初始化桶
    bucketNumber = len(array)
    bucketArray = []
    for i in range(bucketNumber):
        t = []
        bucketArray.append(t)

    # 2.数列的元素放入桶
    for i in array:
        index = int((i - min) / (max - min) * (bucketNumber - 1))
        bucketArray[index].append(i)

    # 3.桶内的元素排序
    for i in array:
        bucketArray[i].sort()

    # 4.返回排好序的集合
    sortedArray = []
    for bucket in bucketArray:
        for element in bucket:
            sortedArray.append(element)

    return sortedArray

if __name__ == '__main__':
    array = [3, 3, 3, 7, 9, 1, 7, 1, 3, 4]
    bucketArray = sortBucket(array)
    print(bucketArray)

输出结果

[1, 1, 3, 3, 3, 3, 4, 7, 7, 9]

Process finished with exit code 0

  这里有一个不是非常明白的地方,就是 第二步中数列元素放入桶,计算index的算法:当前差值/全局差值*数列的长度减一(按照比例定位),在网上也看了其他的文章,有的文章里计算index的算法直接是:当前差值/数列长度。然后,我代入了几个元素,发现,还是前者的算法计算出来的下标更加精确。

桶排序的复杂度

  假设原始数列的元素个数是N,桶的数量的M,平均每个桶内的元素数量的N/M

  求最值,计算量N

  初始化桶,计算量M

  数列的元素放入桶,计算量N

  每个桶内元素排序,由于使用了O(n log n)算法,计算量是M(N/M * log N/M)=N(log N/M)

  最后返回排好序的集合,计算量是N

  综上所述,计算量是 3N+M+ N(log N - log M),去掉系数O(N+M+N(log N - log M))

假如M=N,则时间复杂度O(N+M),近似O(N)

  空间复杂度:很明显是原始数组的空间N 加上 桶的空间M,是N+M

桶排序的缺陷

假如元素分布极不均衡,比如全部在最后一个桶内,则此时的时间复杂度就退化到了O(n*log n),并且空间复杂度浪费了很多,因为创建了很多无用的空桶

posted @ 2018-11-05 00:22  Bug开发攻城狮  阅读(1274)  评论(0编辑  收藏  举报