基数排序
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))时间内将这些数排好序。