思路:
按照个位—>十位->百位这个位数,从低位到高位,依次对待排序数组执行排序,直到最后一位,排出来的结果集就是已完成排序的结果:
比如:有三个数字: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__) */
算法总结:
该算法的稳定性取决于用于每一位上的每轮排序所选择的算法的稳定性,同时,其跟计数排序一样,有一定的前提条件(正整数)和空间代价.