基数排序
前面介绍的计数排序是一种线性时间(即时间复杂度为 O ( n ) O(n) O(n))的排序算法,这一篇介绍另外一种也是线性时间的排序方法:基数排序。
原理
基数排序最早是用于打孔卡片制表机上的算法,它可以给打孔的卡片进行排序。我们把打孔改为用数字表示,则它的基本思想是将整数按位数依次排序。步骤如下:
- 统一数据长度为相同的位数,数位较短的数前面补零。
- 按照个位数进行排序。
- 按照十位数进行排序。
- 按照百位数进行排序。
- 依次类推,一直到按照最高位进行排序。然后就结束了。
其中对每个位数进行排序时需要用稳定的排序算法。如果这个稳定的排序算法可以在线性时间完成,则基数排序也可以在线性时间完成。典型的,我们可以用前面介绍过的计数排序。
实现
按照以上原理我们来用代码实现。
下面就是用C语言实现的代码。
- 要排序的数组a有n个元素。分两个函数来实现。
- radix_sort 中先找到a中元素的最大值,再按给定基数radix计算最大位数,然后从低位到最高位依次调用 count_sort_radix 进行排序。注意基数radix的值是可以调整的,其大小会影响排序效率。
- count_sort_radix 是由前面介绍过的计数排序修改而来,按第d位进行计数排序,注意a中所有元素的每一位数的值都在[0,k]范围内。
/* a中所有元素的每一位数的值都在[0,k]范围内。 */
/* d表示按第几位进行排序,0表示按个位排序, */
/* 1表示按十位,2表示按百位,以此类推。 */
void count_sort_radix(int a[], int n, int k, int d)
{
int *b, *c;
int i;
int num = 1; //便于提取出a中的某一位数的值
b = (int*)malloc(sizeof(int)*n);
if (b==NULL) return;
c = (int*)malloc(sizeof(int)*(k+1));
if (c==NULL) {
free(b);
return;
}
memset(c, 0, sizeof(int)*(k+1));
while