八、计数排序及其应用分析

1 本节思路

之前的算法的最基本的思想是比较元素大小,所以算法复杂度最好是 Θ ( n l o g n ) \Theta(nlogn) Θ(nlogn),本节不再基于元素比较,而是基于计数的Counting sort,然后应用在Radix sort上。

2 Counting sort

2.1 算法思想

Counting sort算法的思想比较简单,就是通过统计每个数字的的个数确定每个数字的位置,譬如【8,6,2】这三个数,通过计数统计知道#8=1,#6=1,#2=1,很自然就是2排正位置1上,6排在位置1+1=2上,8排在位置2+1=3上,因为每个数字都是不重复,所以看起来很low,考虑到有充分数字的情况,就会领会到这个算法的巧妙之处了。

2.2 算法演示

在这里插入图片描述

2.3 算法描述

在这里插入图片描述

2.4 算法实现

# -*- coding: utf-8 -*-
import collections


def counting_sort(A, B, k):
    # let C[0..k] be a new array
    C = [0] * (k + 1)
    for i in range(k + 1):
        C[i] = 0
    for j in range(1, len(A)):
        C[A[j]] = C[A[j]] + 1
    # C[i] now contains the number of elements equal to i.
    for i in range(1, k + 1):
        C[i] = C[i] + C[i - 1]
    # C[i] now contains the number of elements less than or equal to i.
    for j in range(len(A) - 1, 0, -1):
        B[C[A[j]]] = A[j]
        C[A[j]] = C[A[j]] - 1


if __name__ == '__main__':
    A = ['x', 2, 5, 3, 0, 2, 3, 0, 3]
    B = [0] * len(A)
    k = max(A[1:])
    print('before sort:', A[1:])
    counting_sort(A, B, k)
    print('after sort:', B[1:])

运行结果:

before sort: [2, 5, 3, 0, 2, 3, 0, 3]
after sort: [0, 0, 2, 2, 3, 3, 3, 5]

2.5 算法分析

容易得到Counting sort的算法复杂度是 O ( k + n ) O(k+n) O(k+n),k为集合中元素个数,n为排序序列中元素个数,因为 k < n k<n k<n,所以可以认为这个算法是线性时间复杂度,其原因就是空间换时间,所以 其用途在于小范围内的数据,如果数据范围过大(排序的元素个数不一定很多)会占用大量的内存,下面Radix sort正好可以应用到这一点。

3 Radix sort

3.1 Radix sort算法思想

Radix sort按位从后至前排序,因为要防止重复数字问题,所以顺序是从后至前。下面的演示很简单的表达了这种思想:
在这里插入图片描述

3.2 算法描述

在这里插入图片描述
这里stable sort 指的是counting sort。

3.3 算法分析

在这里插入图片描述

  • 考虑一个极端的情况,在一个b=32位的计算机上,每一个数字都可以表示为b个bit的序列,此时 b = l o g 2 n b=log_2{n} b=log2n,应用上面的lemma8.3容易得到,在这种情况下使用RADIX-SORT的算法复杂度是 Θ ( b ( n + 2 ) ) = Θ ( l o g n ( n + 2 ) ) \Theta(b(n+2))=\Theta(logn(n+2)) Θ(b(n+2))=Θ(logn(n+2)),之前的基于“元素比较”排序算法没有什么提高。
  • 考虑另一个方向的极端情况,假如计算机内存超级大随便用(不考虑缓存消耗),那么上面问题的复杂度是 Θ ( n + 32 ) \Theta(n+32) Θ(n+32),理论上完美,实际上不可信。
  • 两个极端的情况之间存在着一种权衡,这种权衡关系如下面lemma8.4所示,这个lemma8.4中使用适当的颗粒度r作为一位进行counting sort。

在这里插入图片描述

  • 有点问题。。。待续。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值