10.基数排序
基数排序的基本思想
- 基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。
- 基数排序的发展:(计数→桶→基数排序)
计数排序:每个桶只存储单一键值;
桶排序:每个桶存储一定范围的数值;
基数排序:根据键值的每位数字来分配桶。
静态图解:
- 按照个位数进行排序;
- 按照十位数进行排序;
- 按照百位数进行排序,此时序列有序。
基数排序的算法步骤:
获取序列A最大值并确定最大位数,从个位开始,按位进行桶排序(调用基数排序子函数):
- 初始化10个桶bucket和临时数组result;
- 遍历序列A,将数据出现的次数存在相应的桶bucket中;
- 调整桶bucket中各元素的值,调整后的值就是待排序列A中元素在result中的位置;
- 将待排序列元素填入result中(后入先出顺序);
- result全部排好后,将其复制回待排序列A。
动态图解:
C++代码实现
#include <iostream>
#include <time.h>
using namespace std;
/*排序方法类*/
class MySort {
public:
int n;
int* A;
//构造函数 ,便于挑选不同的排序方法
MySort(int N) {
this->n = N;
A = new int[this->n];
this->SetArray();
}
//随机初始化数组
void SetArray() {
srand(time(0));
for (int i = 0; i < n; i++) {
A[i] = rand() % 100 + 1;
}
}
//打印数组
void Print() {
for (int i = 0; i < n; i++) {
cout << A[i] << " ";
}
cout << endl;
}
//基数排序主函数
void radixsort(int* A, int n) {
int imax = 0; //获取数组中的最大键值
for (int i = 0; i < n; i++)imax = imax > A[i] ? imax : A[i];
for (int iexp = 1; imax / iexp > 0; iexp *= 10)
_radixsort(A, n, iexp); //从个位开始,对数组A按位进行基数排序
}
//按位排序子函数
void _radixsort(int *A, int n, int exp) {
int *result = new int[n]; //存放桶中收集数据后的临时数组
int bucket[10] = { 0 }; //初始化10个桶
//遍历A,将数据出现的次数存储在桶bucket中
for (int i = 0; i < n; i++)
bucket[(A[i] / exp) % 10]++;
//调整bucket各元素的值,调整后的值就是A中元素在result中的位置
for (int i = 1; i < 10; i++)
bucket[i] = bucket[i] + bucket[i - 1];
//将A中的元素填充到result中(从后往前排,先入后出)
for (int i = n - 1; i >= 0; i--) {
int iexp = (A[i] / exp) % 10;
result[bucket[iexp] - 1] = A[i];
bucket[iexp]--;
}
//将排序好的数组result复制回A中
memcpy(A, result, n * sizeof(int));
}
};
int main() {
//初始化数组
int N;
cout << "请输入数组长度:";
cin >> N;
MySort sort1(N); //构造排序方法类
cout << endl;
cout << "基数排序前:";
sort1.Print();
sort1.radixsort(sort1.A,N); //基数排序
cout << "基数排序后:";
sort1.Print();
cout << endl;
return 0;
}
代码验证: