排序算法(四) 基数排序
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;
}
基本思路:看排序数组中最大值的位数,比如说最大值是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;
}
相关文章推荐
- 排序算法复习(Java实现)(二): 归并排序,堆排序,桶式排序,基数排序
- 经典排序算法 - 基数排序Radix sort
- 排序算法之基数排序
- 经典排序算法 - 基数排序Radix sort
- 经典排序算法 - 基数排序Radix sort
- 程序员必须掌握的8种排序算法(八):基数排序
- 常用排序算法总结8一一基数排序
- 数据结构 学习笔记(十一):排序(下):快速 / 表 / 桶 / 基数 排序,排序算法的比较
- 排序算法系列:基数排序
- 算法 排序算法之基数排序
- 基数排序,一种很费内存但是快得一塌糊涂的排序算法。
- 排序之表排序、基数排序及所有排序算法比较
- 经典排序算法 - 基数排序Radix sort
- 经典排序算法 - 基数排序Radix sort
- 排序算法之基数排序
- 排序算法之基数排序
- 软考之排序算法(四)——归并排序、基数排序
- 排序算法系列:基数排序
- 基本排序算法(冒泡排序 选择排序 插入排序 快速排序 归并排序 基数排序 希尔排序)
- 排序算法: 基数排序