基数排序是非比较排序方法中比较重要的排序。一般情况下,我们都是基于FIFO桶对其实现。基于桶的方法见下面文章:
(2条消息) C++实现排序算法_星星典典的博客-优快云博客https://blog.youkuaiyun.com/ymhdt/article/details/123293536
本文采用另外一种方式,基于词频表的实现。
这里说的词频表可以理解为在数组中某一类数字出现的次数。在基数排序中,我们定义一张表,使用count数组作为容器,用于记录数组 “某位置上 <=i 的” 这类数字出现的次数
代码实现C++
//获取it在i位置上的数字,i=0代表个位
int GetNum(int it, int i)
{
int idx = pow(10, i + 1);
idx = it % idx;
idx = idx / pow(10, i);
return idx;
}
//词频表法基数排序
void CardinalitySort(vector<int>& arr)
{
// 获取最大值,确认排序次数。排序次数为最大值的位数
int temp = arr[0];
for (int it : arr)
{
temp = it > temp ? it : temp;
}
temp = log10(temp);
// 从个位数字开始(当i=0,代表遍历个位数字),依据每位上的数字入桶,然后依据先入先出的规则出桶
for (int i = 0; i <= temp; ++i)
{
// 词频表
vector<int> buckets(10, 0);
//入桶
for (int it : arr)
{
//入桶保存词频
buckets[GetNum(it,i)]++;
}
//构建 <= j的数字的表
for (int j = 1; j < buckets.size(); ++j)
{
buckets[j] += buckets[j - 1];
}
//利用辅助表排序
vector<int> help(arr.size());
for (int ii = arr.size()-1; ii >= 0; --ii)
{
int idx = GetNum(arr[ii], i);
help[--buckets[idx]] = arr[ii];
}
//反向填充
arr = help;
}
}