基数排序:
基数排序过程无须比较关键字,而是通过“分配”和“收集”过程来实现排序,它的时间复杂度可达到线性阶:O(n)。(ps:kN)。对于十进制数来说,每一位的数在[0,9]之中,d位的数,则有d列。基数排序首先按低位有效数字进行排,然后逐次向上一位进行排序,直到最高位排序结束。
约定: 待排数字中没有0,没有负数(有负数,做一次转换全部变为正数即可)
算法过程:
(1)、假设有欲排数据序列如下所示:
73 22 93 43 55 14 28 65 39 81。
首先根据个位数的数值,在遍历数据时将它们各自分配到编号0至9的桶(个位数值与桶号一一对应)中。
分配结果(逻辑想象)如下图所示:
分配结束后。接下来将所有桶中所盛数据按照桶号由小到大(桶中由顶至底)依次重新收集串起来,得到如下仍然无序的数据序列:
81 22 73 93 43 14 55 65 28 39
(2)、接着,再进行一次分配,这次根据十位数值来分配(原理同上),分配结果(逻辑想象)如下图所示:
分配结束后。接下来再将所有桶中所盛的数据(原理同上)依次重新收集串接起来,得到如下的数据序列:
14 22 28 39 43 55 65 73 81 93。
(3)以此类推……
如果排序的数据序列有三位数以上的数据,则重复进行以上的动作直至最高位数为止。
代码:
#include<iostream>
#include<cmath>
#include<vector>
using namespace std;
/**********************************/
//函数声明:
void sort(int arr[],int d,int length);
void putInBucket(int data,int digitOn);
int getDigitOn(int src,int d);
/**********************************/
/***********************************/
//全局变量:
vector<int> bucket[10];
//将数组arr,按d这个位来分配和收集
void sort(int arr[],int length){
int d=1;//入桶依据的位初始化为1
int maxn=arr[0];//数组的最大值
for(int i=1;i<length;i++){
maxn=max(maxn,arr[i]);
}
int dNum=1; //最大值有多少位
while(maxn/10!=0){
dNum++;
maxn/=10;
}
while(d<=dNum){
//依据第二个参数入桶和出桶
sort(arr,d++,length);
}
}
// 重载的sort:将数组arr, 按d这个位来分配和收集
void sort(int arr[],int d,int length){
//全部入桶
for(int i=0;i<length;i++){
putInBucket(arr[i],getDigitOn(arr[i],d));
}
//出桶
//每个桶中的元素依次压入原数组
int k=0;
for(int j=0;j<10;j++){
while(bucket[j].size()){
arr[k++]=bucket[j].front();
bucket[j].erase(bucket[j].begin()); //比较巧妙,移除第一个元素!
}
}
}
//得到十进制数src的第d位:
int getDigitOn(int src,int d){
return src/(int)(pow(10,d-1))%10;
}
void putInBucket(int data,int digitOn){
switch(digitOn){
case 0:
bucket[0].push_back(data);
break;
case 1:
bucket[1].push_back(data);
break;
case 2:
bucket[2].push_back(data);
break;
case 3:
bucket[3].push_back(data);
break;
case 4:
bucket[4].push_back(data);
break;
case 5:
bucket[5].push_back(data);
break;
case 6:
bucket[6].push_back(data);
break;
case 7:
bucket[7].push_back(data);
break;
case 8:
bucket[8].push_back(data);
break;
case 9:
bucket[9].push_back(data);
break;
}
}
int main(){
int arr[]={18,13,17,26,29,38,31,69,51};
int len=9;
sort(arr,len);
//打印结果:
for(int i=0;i<len;i++){
cout<<arr[i]<<" ";
}
return 0;
}
得到十进制数src的第d位(需背住):
//得到十进制数src的第d位:
int getDigitOn(int src,int d){
return src/(int)(pow(10,d-1))%10;
}
运行结果:
小结:
计数排序: 适用于小范围数据;
桶排序: 适用于均匀分配的数据。