原理:
我们先在待排序数列里面找到这些元素最大的位数,然后按照计数排序的思想对待排序序列个位、十位、百位、...分别进行计数排序。最终形成有序的序列。
举例:
原始数据
31,12,5,57,2,31,90,32,95,76
我们分别去取原始数据的个位。
31,12,5,57,2,31,90,32,95,76
统计个位数出现的次数。
1 | 2 | 3 | 0 | 0 | 2 | 1 | 1 | 0 | 0 |
B序列
接下来我们对B序列进行相邻数据累加,并记录在下标较大的位置,求出各个个位数比他们每个小的数据有几个。
1 | 3 | 6 | 6 | 6 | 8 | 9 | 10 | 10 | 10 |
逆序遍历原始数据的个位。
倒数第一个为6,对应B序列中下标为6的元素9,那么这个数先排在第八位上。
76 |
此时B序列的下标为6的元素-1。为避免重复的数字。
1 | 3 | 6 | 6 | 6 | 8 | 8 | 10 | 10 | 10 |
倒数第二个为5,对应B序列中下标为5的元素8,那么这个数先排在第七位上。
A序列
95 | 76 |
此时B序列的下标为5的元素-1。
1 | 3 | 6 | 6 | 6 | 7 | 8 | 10 | 10 | 10 |
倒数第三个为2,对应B序列中下标为2的元素6,那么这个数先排在第五位上。
32 | 95 | 76 |
此时B序列的下标为2的元素-1。
B序列
A序列
此时B序列的下标为0的元素-1。
B序列
A序列
B序列
A序列
B序列
A序列
B序列
A序列
B序列
A序列
B序列
A序列
此时B序列的下标为1的元素-1。
B序列
B序列
接下来我们对B序列进行相邻数据累加,并记录在下标较大的位置,求出各个个位数比他们每个小的数据有几个。
B序列
C序列
B序列
C序列
1 | 3 | 5 | 6 | 6 | 7 | 8 | 10 | 10 | 10 |
倒数第四个为0,对应B序列中下标为0的元素1,那么这个数先排在第零位上。
90 | 32 | 95 | 76 |
此时B序列的下标为0的元素-1。
0 | 3 | 5 | 6 | 6 | 7 | 8 | 10 | 10 | 10 |
倒数第五个为1,对应B序列中下标为1的元素3,那么这个数先排在第二位上。
90 | 31 | 32 | 95 | 76 |
此时B序列的下标为1的元素-1。
0 | 2 | 5 | 6 | 6 | 7 | 8 | 10 | 10 | 10 |
倒数第六个为2,对应B序列中下标为2的元素5,那么这个数先排在第四位上。
90 | 31 | 2 | 32 | 95 | 76 |
此时B序列的下标为2的元素-1。
0 | 2 | 4 | 6 | 6 | 7 | 8 | 10 | 10 | 10 |
倒数第七个为7,对应B序列中下标为7的元素10,那么这个数先排在第九位上。
90 | 31 | 2 | 32 | 95 | 76 | 57 |
此时B序列的下标为7的元素-1。
0 | 2 | 4 | 6 | 6 | 7 | 8 | 9 | 10 | 10 |
倒数第八个为5,对应B序列中下标为5的元素7,那么这个数先排在第六位上。
90 | 31 | 2 | 32 | 5 | 95 | 76 | 57 |
此时B序列的下标为5的元素-1。
0 | 2 | 4 | 6 | 6 | 6 | 8 | 9 | 10 | 10 |
倒数第九个为2,对应B序列中下标为2的元素4,那么这个数先排在第三位上。
90 | 31 | 12 | 2 | 32 | 5 | 95 | 76 | 57 |
此时B序列的下标为2的元素-1。
0 | 2 | 3 | 6 | 6 | 6 | 8 | 9 | 10 | 10 |
倒数第十个为1,对应B序列中下标为1的元素2,那么这个数先排在第一位上。
90 | 31 | 31 | 12 | 2 | 32 | 5 | 95 | 76 | 57 |
此时B序列的下标为1的元素-1。
0 | 1 | 3 | 6 | 6 | 6 | 8 | 9 | 10 | 10 |
此时我们拿到了A序列。
90,31,31,12,2,32,5,95,76,57
我们分别去取A序列的十位。
90, 31, 31, 12, 02, 32, 05, 95, 76, 57
我们分别去取A序列的十位。
90, 31, 31, 12, 02, 32, 05, 95, 76, 57
清空B序列,重新统计十位数字出现的次数。
2 | 1 | 0 | 3 | 0 | 1 | 0 | 1 | 0 | 2 |
接下来我们对B序列进行相邻数据累加,并记录在下标较大的位置,求出各个个位数比他们每个小的数据有几个。
2 | 3 | 3 | 6 | 6 | 7 | 7 | 8 | 8 | 10 |
倒数第一个为5,对应B序列中下标为5的元素7,那么这个数先排在第六位上。
57 |
此时B序列的下标为5的元素-1。
2 | 3 | 3 | 6 | 6 | 6 | 7 | 8 | 8 | 10 |
倒数第二个为7,对应B序列中下标为7的元素8,那么这个数先排在第七位上。
57 | 76 |
此时B序列的下标为7的元素-1。
2 | 3 | 3 | 6 | 6 | 6 | 7 | 7 | 8 | 10 |
倒数第三个为9,对应B序列中下标为9的元素10,那么这个数先排在第九位上。
57 | 76 | 95 |
此时B序列的下标为9的元素-1。
2 | 3 | 3 | 6 | 6 | 6 | 7 | 7 | 8 | 9 |
倒数第四个为0,对应B序列中下标为0的元素2,那么这个数先排在第一位上。
5 | 57 | 76 | 95 |
此时B序列的下标为0的元素-1。
1 | 3 | 3 | 6 | 6 | 6 | 7 | 7 | 8 | 9 |
倒数第五个为3,对应B序列中下标为3的元素6,那么这个数先排在第五位上。
5 | 32 | 57 | 76 | 95 |
此时B序列的下标为3的元素-1。
1 | 3 | 3 | 5 | 6 | 6 | 7 | 7 | 8 | 9 |
倒数第六个为0,对应B序列中下标为0的元素1,那么这个数先排在第零位上。
2 | 5 | 32 | 57 | 76 | 95 |
此时B序列的下标为0的元素-1。
0 | 3 | 3 | 5 | 6 | 6 | 7 | 7 | 8 | 9 |
倒数第七个为1,对应B序列中下标为1的元素3,那么这个数先排在第二位上。
2 | 5 | 12 | 32 | 57 | 76 | 95 |
此时B序列的下标为1的元素-1。
0 | 2 | 3 | 5 | 6 | 6 | 7 | 7 | 8 | 9 |
倒数第八个为3,对应B序列中下标为3的元素5,那么这个数先排在第四位上。
2 | 5 | 12 | 31 | 32 | 57 | 76 | 95 |
此时B序列的下标为3的元素-1。
0 | 2 | 3 | 4 | 6 | 6 | 7 | 7 | 8 | 9 |
B序列
倒数第九个为3,对应B序列中下标为3的元素4,那么这个数先排在第三位上。
2 | 5 | 12 | 31 | 31 | 32 | 57 | 76 | 95 |
C序列
此时B序列的下标为3的元素-1。
0 | 2 | 3 | 3 | 6 | 6 | 7 | 7 | 8 | 9 |
B序列
倒数第十个为9,对应B序列中下标为9的元素9,那么这个数先排在第八位上。
2 | 5 | 12 | 31 | 31 | 32 | 57 | 76 | 90 | 95 |
此时B序列的下标为9的元素-1。
0 | 2 | 3 | 3 | 6 | 6 | 7 | 7 | 8 | 8 |
此时C序列为排列好的数列。如果位数多,按照此理论继续向下推。
代码:
void RadixSort(int a[], int nlen)
{
auto Digit = [&]()->int
{
int num = 10, digit = 1;
for (int i = 1; i != nlen; ++i)
{
while (a[i] / num)
{
num *= 10;
++digit;
}
}
return digit;
};
int MyDigit = Digit();
int arr[10] = { 0 };
int radix = 1;
int *temp = new int[nlen];
for (int i = 1; i <= MyDigit; ++i)
{
for (int j = 0; j != nlen; ++j)
{
++arr[(a[j] / radix) % 10];
}
for (int j = 1; j != sizeof(arr) / sizeof(int); ++j)
{
arr[j] += arr[j - 1];
}
for (int j = nlen - 1; j >= 0; --j)
{
temp[--arr[(a[j] / radix) % 10]] = a[j];
}
for (int j = 0; j != nlen; ++j)
{
a[j] = temp[j];
}
for (int& x : arr)
{
x = 0;
}
radix *= 10;
}
delete[] temp;
temp = nullptr;
}
总结:
基数排序是按照计数排序演变而来的,通过选取各个元素的位数进行排序(由低位到高位)。最终得到排序好的序列。相比计数排序而言,减小了运行时的内存消耗,时间复杂度为O(N)。