基数+计数排序
基数排序思想就是先按照优先级低的关键字排序,然后一层层来就可以得到正确的答案。
先来理解其正确性:我们对于一串数的低优先级关键字排序后,得到的序列再按照高优先级关键字排序,就可以得到相同高关键字内按照低关键字排序的结果。但是要保证不在高关键字排序下无故交换原本的序列顺序。
可能你要问这样做的话为什么不直接 sort,因为在我们将计数排序思想后,我们的排序算法更快。
对于关键字开其值域的桶,然后桶排序,复杂度 \(O(n+k)\),其中 \(k\) 为关键字值域。
然后我们可以通过处理桶的前缀和得到关键字的排名,然后倒序放入数组就可以保证不在高关键字排序下无故交换原本的序列顺序。
然后需要我们每个关键字搞一次,那么复杂度就是 \(O(p(n+k) )\), \(p\) 为关键字个数。
对于数值排序,我们只需要将其转换成 \(k\) 进制,然后按照进制位排序即可, 复杂度 \(O(\log_k n(n+k) )\)
给出按照数值排序的基数排序(每个进制数位为一个关键字,优先级从高位到低位)
inline void radix_sort(int *data,int len,int radix=512){
int *tmp=new int[len+3];
int *cnt=new int[radix+3];
int mx=0;
for(int i=1;i<=len;++i){
if(mx<data[i])
mx=data[i];
}
int p=1;
for(int d=0;d<4;++d){
for(int i=0;i<radix;++i){
cnt[i]=0;
}
for(int i=1;i<=len;++i){
int k=(data[i]/p)%radix;
++cnt[k];
}
for(int i=1;i<radix;++i){
cnt[i]+=cnt[i-1];
}
for(int i=len;i>=1;--i){
int k=(data[i]/p)%radix;
tmp[cnt[k]--]=data[i];
}
std::swap(data,tmp);
p*=radix;
}
delete []tmp;
tmp=NULL;
delete []cnt;
cnt=NULL;
}