1.大体思路
基数排序是一种整数排序算法,先写出提取整数每一位数字的子函数,然后从最低位开始(必须是从最低位开始),依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。
2.代码
#include <iostream>
#include <algorithm>
#include <ctime>
using namespace std;
//const int N = 5;
void InitArr(int *nArr, int nLen) { //初始化数组
srand(time(NULL));
for(int i = 0; i < nLen; ++i) {
nArr[i] = rand() % 500;
//nArr[i] = i;
}
}
void PrintArr(int *nArr, int nLen) {
for(int i = 0; i < nLen; ++i) {
cout << nArr[i] << " ";
}
cout << endl;
}
void Swape(int *p1, int *p2) {
int nTmp = *p1;
*p1 = *p2;
*p2 = nTmp;
}
void RandomSort(int *nArr, int nLen) {
srand(time(NULL));
for(int i = 0; i < nLen; ++i) {
int nIndex = rand() % nLen;
Swape(&nArr[i], &nArr[nIndex]);
//Sleep(2000); //等待2s,更新随机种子
}
}
//获取每一位上的数字
int Digit(int nNum, int w) {
int nTmp = 1;
for(int i = 0; i < w - 1; ++i) {
nTmp *= 10;
}
return (nNum / nTmp) % 10;
}
void RadixSort(int *nArr, int nLen, int w) {
int i;
int radixArrays[10][nLen + 1];
for(i = 0; i < 10; ++i) {
radixArrays[i][0] = 0; //此处记录这组数据的个数
}
for(int pos = 1; pos <= w; ++pos) { //从个位开始,且只能从个位开始
for(i = 0; i < nLen; ++i) { //分配过程
int num = Digit(nArr[i], pos);
int index = ++radixArrays[num][0];
radixArrays[num][index] = nArr[i];
}
int j = 0;
for(i = 0; i < 10; ++i) { //收集
for(int k = 1; k <= radixArrays[i][0]; ++k) {
nArr[j++] = radixArrays[i][k];
}
radixArrays[i][0] = 0; //复位
}
PrintArr(nArr, nLen);
}
}
int main() {
int Len = 20;
int Arr[Len];
InitArr(Arr, Len);
PrintArr(Arr, Len);
RandomSort(Arr, Len);
PrintArr(Arr, Len);
cout << endl;
RadixSort(Arr, Len, 3);
// PrintArr(Arr, Len);
return 0;
}
3.运行结果
4.总结
基数排序的时间复杂度是 O(k*n) ,其中 n 是排序元素个数,k 是数字位数,注意这不是说这个时间复杂度一定优于 O(nlogn),k的大小取决于数字位的选择(比如比特位数),和待排序数据所属数据类型的全集的大小;k决定了进行多少轮处理,而 n 是每轮处理的操作数目,k≈logB(N), B表示每一位存在不同数的个数,N是待排序数据集全集的势(可以理解为最大值),关键码的取值范围为radix,一趟分配时间复杂度为O(n),一趟收集时间复杂度为O(radix),共进行k趟分配和收集。
如果考虑和比较排序进行对照,基数排序的形式复杂度虽然不一定更小,但由于不进行比较,因此其基本操作的代价较小,而且在适当选择的 B 之下,k一般不大于 log n,所以基数排序一般要快过基于比较的排序,比如快速排序。
基数排序属于非比较排序
基数排序的效率和初始序列是否有序没有关联。
基数排序属于稳定排序。
裸的基数排序只针对非负整数进行排序。