算法:排序(三)

计数排序与基数排序

利用桶排序的思想可以达到O(N)的时间复杂度,但仅限于特定的情况。

计数排序

已知数据取值在狭小且有限的集合内,则可以使用计数排序。思路是预先准备好表征元素取值的计数桶,遍历元素时,使得表征该元素取值的桶计数值加一。遍历完成后倒出元素即可。

算法:排序(三)_第1张图片
int* countingSort(int* A, int n) {
    //获取最大最小值以便分配桶
    int min=A[0],max=A[0];
    for(int i=1;imax)
            max=A[i];
        if(A[i]

基数排序

基数排序可以看做是计数排序的扩展。适用于元素有多个键值,键值取值狭小且有限的情况。思路是按照键值优先级从低到高进行排序。
举例:正整数的个位/十位/百位数字就是表征数字大小的各个键值,先按照个位数字放入各个桶内,然后倒出;再按照十位/百位数字继续此操作。

CODE

int* radixSort(int* A, int n) {
    const int M=10;
    //临时存储数据
    int* s=new int[n];
    //计数:每个键值各对应多少元素
    int* c=new int[M]();
    //被除数,用以计算当前位置的数字
    int x=1;
    int number;
    for(int t=0;t<5;++t){  //假设元素不超过五位数
        //清零计数数组
        for(int m=0;m=0;--i){
            number=A[i]/x%10;
            s[--c[number]]=A[i];
        }
        //从桶中倒回数组
        for(int i=0;i

注意

  • 以上代码为了节省空间,所有的桶都位于数组s上的某一段,通过计数产生c数组,然后累加得到每个桶的尾后指针位置,以此访问桶。


  • 元素入桶时根据尾后指针进行遍历,所以需要从后向前遍历数组。
  • 如果不考虑空间花费,可以通过指针数组来创建类似于二维数组的结构来构造M个桶;或者使用队列等数据结构来处理。

你可能感兴趣的:(算法:排序(三))