您的位置:首页 > 其它

排序算法(四) 基数排序

2017-03-26 19:54 232 查看
本篇博客介绍基于顺序表的实现 LSD,MSD 两种方式

基本思路:看排序数组中最大值的位数,比如说最大值是999,就是三位 K1K2K3,先按K3扫描一遍数组,分别记下K3位为0的个数,为1的个数,……为9的个数,用数组coun[10]来记录,再使用一个数组addr[10]来记录每个桶的起始位置

计算起始地址:addr[idx] = addr[idx-1] + count[idx -1], 再扫描数组根据addr中的起始位置,依次把元素归为。

举个例子:

序列:278,109,063,930,589,184,505,269,008,083

    0  1  2  3  4  5  6  7  8  9

count[]:1  0  0  2  1  1  0  0  2  3

Addr[] :0  1  1  1  3  4  5  5  5  7

第一次排序(个位):以278为例addr[8] 为5,就把元素278放到数组5号位置,然后把addr[8]++

(1)LSD:从最低位开始排序,循环上面的操作,把次高位排序,再把最高位排序。

代码:

int GetMaxBit(int *arr,size_t size) //获取最大值的位数
{
int count = 0;
int radix = 1;
for (size_t i = 0; i < size; ++i)
{
while (arr[i] > radix)
{
count++;
radix *= 10;
}
}
return count;
}
void RadixSortLSD(int *arr, size_t size) //按最低位开始排序
{
size_t MaxBit = GetMaxBit(arr, size);
int radix = 1;
int* bucket = new int[size];
for (size_t BitIdx = 1; BitIdx <= MaxBit; ++BitIdx)
{

//统计个位 出现的次数 放到桶中
int count[10] = { 0 };
for (size_t idx = 0; idx < size; ++idx)
{
count[arr[idx]/radix % 10]++;
}

//计算每个桶的起始位置: 上一个桶的起始地址+上一个桶内的元素个数
int Addr[10] = { 0 };
for (size_t j = 1; j < 10; ++j)
{
Addr[j] = Addr[j - 1] + count[j - 1];
}
//归置元素,排序

for (size_t index = 0; index < size; ++index)
{
int k = arr[index] / radix % 10;//桶号
bucket[Addr[k]] = arr[index];
Addr[k]++;
}
memcpy(arr, bucket, size*sizeof(bucket[0]));
radix *= 10;
}
delete[] bucket;
}(2) MSD以最高位排序是一个递归过程
   ①先把最高位排序,找出count[]数组中大于1的。

   ②再对个数大于1的,再次进行此低位排序。直到最低位。

代码中有解释:

void _RadixSortMSD(int *arr, size_t left, size_t right, int* bucket, int bit) //[)
{
if (bit == 0)
return;
int radix = (int)pow(10,bit -1);

//统计百(十 个)位 出现的次数 放到桶中
int count[10] = { 0 };
for (size_t idx = left; idx < right; ++idx)
{
count[arr[idx] / radix % 10]++;
}

//计算每个桶的起始位置: 上一个桶的起始地址+上一个桶内的元素个数
int Addr[10] = { 0 };
for (size_t j = 1; j < 10; ++j)
{
Addr[j] = Addr[j - 1] + count[j - 1];
}
//归置元素,排序

for (size_t index = left; index < right; ++index)
{
int k = arr[index] / radix % 10;//桶号
bucket[left + Addr[k]] = arr[index];
Addr[k]++;
}
memcpy(arr + left, bucket + left, (right - left)*sizeof(bucket[0]));

//扫描count桶中 查找个数大于1的元素
size_t m = 0;
for (; m < 10; ++m)
{
if (count[m] <= 1)
continue;
else
{
int begin = left + Addr[m] - count[m];
int end = begin + count[m];
_RadixSortMSD(arr, begin, end, bucket, bit - 1);
}
}

}

void RadixSortMSD(int *arr,size_t size)
{
size_t bit = GetMaxBit(arr, size);
int * bucket = new int[size];
_RadixSortMSD(arr, 0, size, bucket, bit);
delete[] bucket;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: