您的位置:首页 > 其它

基数排序

2017-12-01 10:00 267 查看
基数排序(Radix Sorting)是一种与其他排序算法完全不同的排序方法,其他的排序算法都是通过关键字之间的比较和移动来完成的,而基数排序则不需要比较,而是采用一种多关键字的思想。

什么是多关键字的思想呢?

给定一组数据,我可以先按个位的大小对所有数进行排序,然后再按十位进行排序,一直到最高位,这样就可以使整组数据变得有效,这样从最低位开始的方法称为最低位优先(Least Significant Digit first)

反之,如果先从最高为的关键字开始,最后再比较最低位,则称之为最高位优先(Most Significant Digit first)

排序过程如下图:



经过一次放置和回收,得到的序列已经按个位有序了,接下来按照次低位再次进行放置和回收。



由此可以看出,如果一组序列中最大的数为两位数,则需要两次的分配和收集,整个分配收集的次数与最大数的位数有关。

求最大位数:

int GetMaxBit(int* array,int size)
{
assert(array);
int base = 10;
int digits = 1;//至少是个位数
for(int i = 0;i < size;++i)
{
while(array[i] >= base)//只要有数大于base,则位数+1
{
++digits;
base *= 10;
}
}
return digits;
}


基数排序需要两个辅助空间,一个是0~9号桶,另一个是计算定位的数组,定位数组是干什么的呢?就是记录每个桶中的数据待会要放回原数组的哪个位置。



下面是代码实现:

void RadixSort(int* array,int size)
{
assert(array);
int* buckets = new int[size];
int base = 1;
int maxbit = GetMaxBit(array,size);
for(int i = 0;i < maxbit;++i)
{
//统计0~9号桶中的个数
int counts[10] = {0};
for(int i = 0;i < size;++i)
{
int num = (array[i]/base)%10;
counts[num]++;
}

//定位数组
int start[10] = {0};
for(int i = 1 ;i < 10;++i)
{
start[i] = start[i - 1] + counts[i - 1];
}

//往桶里扔
for(int i = 0;i < size;++i)
{
int num = (array[i]/base)%10;
int& pos = start[num];
buckets[pos] = array[i];
++pos;
}

memcpy(array,buckets,sizeof(int)*size);
base *= 10;
delete[] buckets;
}
}


时间复杂度:

基数排序的时间复杂度可以理解为O(d*n),d为序列中最大的位数,适用于n值很大,但是关键字较小的序列。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息