基数排序
1、思想与概念
基数排序(radix sort)是一种用在卡片排序机上的算法。基数排序是先按最低有效位进行排序来解决卡片排序问题的。然后算法将所有卡片合并成一叠,其中0号容器中的卡片都在1号容器中的卡片之前,而1号容器中的卡片又在2号容器中的卡片前面,以此类推。之后,用同样的方法按次低有效位对所有的卡片进行排序,并把拍好的卡片再次合并成一叠。重复这一过程,直到对所有的d位数字都进行了排序。此时,所有卡片已按d位数完全排好序。对这一叠卡片的排序仅需要进行d轮。
为了确保基数排序的正确性,一位数排序算法必须是稳定的。卡片排序机所执行的排序是稳定的,但操作员必须确保卡片从容器中被取出时不改变顺序,即使一个容器中的所有卡片在该位都是相同的数字也要确保这一点。
2、算法思路
由于基数排序要确保稳定性,所以可以利用计数排序的思想进行对数组元素进行排序。
基数排序中假设n个d位的元素存放在数组A中,其中第1位是最低位,第n位是最高位。
RADIX-SORT(A,d)
1 for i=1 to d
2 use a stable sort to sort array A on digit i
3、具体实现
/*基数排序*/
#include <iostream>
using namespace std;
#define M 10//每一位数都是0--9,共10个数
//打印数组
void PrintRadixSort(int *arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
//获取数组最大值
int GetMax(int *arr, int len)
{
int tmp = 0;
for (int i = 0; i < len; i++)
{
if (tmp < arr[i])
{
tmp = arr[i];
}
}
return tmp;
}
//计数排序
void CountSort(int *arr, int len, int d)//d代表位数(个十百...)
{
int *b, *c;
b = (int*)malloc(sizeof(int)*len);//存放排序结果
c = (int*)malloc(sizeof(int)*M);//辅助数组
cout << "\nd=" << d << endl;
//将辅助数组置为0
for (int i = 0; i < M; i++)
{
c[i] = 0;
}
//记录数组arr中每个元素的个数
for (int i = 0; i < len; i++)
{
c[(arr[i] / d) % 10]++;
}
cout << "C记录数组arr中每个元素的个数:" << endl;
PrintRadixSort(c, M);
//记录数组arr中比前一个元素大或相等的元素个数
for (int i = 1; i < M; i++)
{
c[i] = c[i] + c[i - 1];
}
cout << "C记录数组arr中比前一个元素大或相等的元素个数:" << endl;
PrintRadixSort(c, M);
//将数组arr中的元素按顺序放入b中
for (int i = len - 1; i >= 0; i--)
{
b[c[(arr[i] / d) % 10]-1] = arr[i];
c[(arr[i] / d) % 10]--;
}
//重新将数组b赋给arr
for (int i = 0; i < len; i++)
{
arr[i] = b[i];
}
cout << "arr数组排序后元素顺序:" << endl;
PrintRadixSort(arr, len);
}
//基数排序
void RadixSort(int *arr, int len)
{
int max = GetMax(arr, len);
for (int i = 1; max / i>0; i *= 10)
{
CountSort(arr, len, i);
}
}
int main/*dm010*/()
{
int len = 0;
int array[] = { 329, 457, 657, 839, 436, 720, 355 };
//数组长度
len = sizeof(array) / sizeof(array[0]);
//打印数组
cout << "Before RadixSort array:" << endl;
PrintRadixSort(array, len);
//基数排序
RadixSort(array, len);
//打印数组
cout << "\nAfter RadixSort array:" << endl;
PrintRadixSort(array, len);
system("pause");
return 0;
}
4、分析
引理1:给定n个d位数,其中每一个数位有k个可能的取值。如果RADIX-SORT使用的稳定排序方法耗时O(n+k),那么它就可以在O(d(n+k))时间内将这些数排好序。
引理2:给定一个d位数和任何正整数r≤b,如果RADIX-SORT使用的稳定排序算法对数据取值区间是0到k的输入进行排序耗时O(n+k),那么它就可以在O((b/r)(n+2r))时间内将这些数排好序。