算法笔记八:基数排序

思路:

按照个位—>十位->百位这个位数,从低位到高位,依次对待排序数组执行排序,直到最后一位,排出来的结果集就是已完成排序的结果:

比如:有三个数字:235,786,241

先按照个位来排:

241,235,786

再按照10位来排:

235,241,786

再按照百位来排:

235,241,786

最终结果:正确!


空间代价:

每轮计数排序中用到的统计数组O(10) +

每轮排序中存放指定位数的值O(n),这步如果CPU资源充足,可以省略,每次都从原始数组中实时进行计算

每轮排序结束后存放结果集的数组O(n)

等于:O(2n) + O(10) ,可近似的等于O(2n)


时间代价:

假设最大位数为B,则总的时间代价为B*每一位上的计数排序的代价

等于:B*O(2n + 10),可近似的等于O(2nB)


算法实现:

#ifndef __p1__BaseNumberSort__
#define __p1__BaseNumberSort__

#include <stdio.h>
#include <math.h>
#include <string.h>


typedef struct number_with_bit {
    int * number;
    int bitValue;
} s_bumber;

//思想
//取个位作为KEY,排序,再取十位作为KEY,排序....直到最高位
//每一位上的排序,又可采取其他排序算法,如:计数排序来实现。因为每一位上的最大值是确定的一个非常小的数字:9,所以这个场景非常适合计数排序
//每一位上的排序的稳定性,决定了基数排序的稳定性
class BaseNumberSort {
    
    
public:
    //求最大值
    int caculateMaxValue(int * data,int size){
        int maxValue = *data;
        for (int i =1; i < size ; i++) {
            if(*(data + i) > maxValue){
                maxValue = *(data + i);
            }
        }
        return maxValue;
    }
    
    //求给定数字的位数,比如:90的位数是2
    int calculateBitCout(int number){
        int bit = 1;
        while(number / ((int)pow(10,bit)) > 0){
            bit++;
        }
        return bit;
    }
    
    //求给定数组的指定位上的值,比如:number = 90,postition =2 ,结果为9
    int calculateBitNumberWithPosition(int number,int position){
        return number / ((int)pow(10,position - 1)) % 10;
    }
    
    //构建原始待排序数组的某位上的值的数组
    s_bumber * buildNumberBitValueArray(int * data,int maxValue,int size){
        s_bumber * arr = new s_bumber [10];
        memset(arr, '\0', sizeof(s_bumber)*10);
        return arr;
    }
    
    //将 出现次数 数组做下处理,转变成给定的数组,前面有多少个比它小的数字,用于每一轮的计数排序
    void dealCountingArray(int * countingArr,int maxValue){
        for (int i = 1; i <= maxValue; i++) {
            *(countingArr + i) += *(countingArr + i -1);
        }
    }
    
    //初始化一个元素为0、长度为size的数组
    int * initZeroData(int size){
        int * data =  new int [size];
        memset(data, 0, sizeof(int) * size);
        return data;
    }
    
    //执行由bitPosition指定位数上的排序
    //originalArray:待排序的数组
    //sortResultArray:每位上排完序以后的数组
    //countingArray:用来在计数排序中进行计数的数组
    //bitvalueArray:存放待排序数组+指定位上的值
    //arraySize:待排序数组大小
    //bitPosition:排第几位
    void doCountingSorInPerBit(int ** originalArray,int ** sortResultArray,int * countingArray,s_bumber * bitvalueArray, int arraySize,int bitPosition){
        
        //清零
        memset(bitvalueArray, '\0', sizeof(s_bumber) * arraySize);
        memset(countingArray, '\0', sizeof(int) * 10);
        memset(*sortResultArray, '\0', sizeof(int) * arraySize);
        
        //求出待排序数组中每个元素在指定位数上的值
        for (int i=0; i < arraySize; i++) {
            (bitvalueArray + i)->bitValue = calculateBitNumberWithPosition(*(*originalArray + i),bitPosition);
            (bitvalueArray + i)->number = (*originalArray + i);
        }
        
        //对 bitvalueArray 执行计数排序
        for (int i=0; i<arraySize; i++) {
            int bitValue = (bitvalueArray + i)->bitValue;
            (*(countingArray + bitValue))++;
        }
        //转换成前面有多少个数
        dealCountingArray(countingArray,9);
        
        //输出当前位上的排序结果
        for (int i = arraySize - 1; i >=0; i--) {
            int bitValue = (bitvalueArray + i)->bitValue;
            int beforNumCount = *(countingArray + bitValue);
            *(*sortResultArray + beforNumCount - 1) = *((bitvalueArray + i)->number);
            (*(countingArray + bitValue))--;
        }
        
        //将排序结果再赋值回去成为下一轮的待排序数组
        int * tmp = *originalArray;
        *originalArray = *sortResultArray;
        *sortResultArray = tmp;
    }
    
    int * doBaseNumberSorint(int * data,int size){
        //初始化结果数组
        int * sortResultArray = initZeroData(size);
        //初始化位数值存放数组
        s_bumber * bitvalueArray = new s_bumber [size];
        //初始化用来计数的数组
        int * countingArray = new int [10];
        
        //求待排序的最大值
        int maxValue = caculateMaxValue(data,size);
        //求最大值的位数
        int bitCount = calculateBitCout(maxValue);
        
        for(int i = 1;i<=bitCount;i++){
            doCountingSorInPerBit(&data,&sortResultArray,countingArray,bitvalueArray, size,i);
        }
        
        //释放资源
        delete [] sortResultArray;
        delete [] bitvalueArray;
        delete [] countingArray;
        
        //这个由外层负责释放
        return data;
    }
    
    //排序入口
    int * do_sorting(int * data,int size){
        return doBaseNumberSorint(data, size);
    }

};

#endif /* defined(__p1__BaseNumberSort__) */


算法总结:


该算法的稳定性取决于用于每一位上的每轮排序所选择的算法的稳定性,同时,其跟计数排序一样,有一定的前提条件(正整数)和空间代价.


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值