基数排序思想逻辑
基数排序思想比较简单,例如有这么一个数组A[14,59,62,88,16]。
第一次,比较个位数,得到数组A1[62,14,16,88,59]
第二次,比较十位数,得到数组A2[14,16,59,62,88]。
…
具体是怎么实现的呢?
分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样
| 0 | 0 | 62 | 0 | 14 | 0 | 16 | 0 | 88 | 59 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
将桶里的数字顺序取出来, 输出结果:[62,14,16,88,59]
再次入桶,不过这次以十位数的数字为准,进入相应的桶,变成下边这样:
由于前边做了个位数的排序,所以当十位数相等时,个位数字是由小到大的顺序入桶的,就是说,入完桶还是有序
| 0 | 14,16 | 0 | 0 | 0 | 59 | 62 | 0 | 88 | 0 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
基数排序时间效率分析
时间效率:设待排序列为n个记录,d个关键码,关键码的取值范围为radix,则进行链式基数排序的时间复杂度为O(d(n+radix)),其中,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行d趟分配和收集。 空间效率:需要2*radix个指向队列的辅助空间,以及用于静态链表的n个指针。
基数排序代码
#include <iostream>
using namespace std;
int32_t GetMaxBit(int32_t numList[], int32_t len) {
auto digit = 1;
for (auto i = 0; i < len; i++) {
auto tmp = 10;
while (numList[i] > tmp) {
digit += 1;
tmp *= 10;
}
}
return digit;
}
void RadixSort(int32_t numList[], int32_t len) {
auto digit = GetMaxBit(numList, len);
vector<int32_t> tmpList(len);
vector<int32_t> count(10);
auto radix = 1;
for (auto i = 0; i < digit; i++) {
for (auto j = 0; j < len; j++) {
//统计每个桶中将要放的总数
auto bit = (numList[j] / radix) % 10;
count[bit]++;
}
for (auto j = 1; j < 10; j++) {
//对每个桶中的每个数值重新定位:
//比如第一个桶有2个数字,第二个桶有1个数字,那么第二个桶中的这个数字的排序应该是在第一个桶的2个数字后面
count[j] += count[j - 1];
}
for (auto j = len - 1; j >= 0; j--) {
//把每个桶中的数字按顺序存起来
auto bit = (numList[j] / radix) % 10;
tmpList[count[bit] - 1] = numList[j];
count[bit]--;
}
for (auto j = 0; j < len; j++) {
numList[j] = tmpList[j];
}
radix *= 10;
}
}
void main() {
int32_t numList[] = { 31, 41, 59, 26, 48, 58, 12, 5, 90, 10, 9, 6, 45};
int32_t len = sizeof(numList) / sizeof(numList[0]);
RadixSort(numList, len);
for (auto num : numList) {
std::cout << num << " ";
}
std::cout << std::endl;
}
返回排序算法分析总结