排序算法(5)-线性时间排序

算法导论有证明,基于比较的排序(插入,选择,归并,快速,堆排序)的渐进时间复杂度下限为O(lg(n))。因此,这里提到的线性时间排序,必然不是基于比较的排序。本质上讲,个人认为这些线性时间排序就是用空间换取时间。

计数排序,a,b均为长度为n的数组,a为输入,b为排序好的数组,要求是a的元素必须都为小于k的非负数,计数排序直接将值作为c数组的寻址

 1 void counting_sort(int a[], int b[], int n, int k)
 2 {
 3     int* c = new int[k];
 4 
 5     for (int i = 0; i < k; ++i)
 6         c[i] = 0;
 7     for (int i = 0; i < n; ++i)
 8         ++c[a[i]];
 9     for (int i = 1; i < k; ++i)
10         c[i] += c[i - 1];
11     for (int i = n - 1; i >= 0; --i)
12     {
13         b[c[a[i]] - 1] = a[i];
14         --c[a[i]];
15     }
16 
17     delete[] c;
18 }

 基排序,最直观的理解是,当所有数的位数都小于d时,我们可以从最低位开始排序,直到最高位,类似于n个百位数,我们先比较个位,再比较十位,再比较百位,就可以完成排序了

void radix_sort(int a[], int n, int d)
{
    for (int i = 0; i < d; ++i)
        // sort array a on digit i by some stable sort method.
}

对于某个位的数字来说,必然小于k(十进制下,小于9),那么我们就可以用计数排序在O(n+k)内完成排序,整个排序在O(d(n+k))内完成。

很显然,计数排序,基排序都只能对非负整数进行排序,对浮点数则无效。桶排序则没有这个限制。桶排序假定数字都在[0,1)区间内,且数组a分布均匀,那么我们可以设置n个小桶将[0,1)区间划分,n*a[i]的整数值就可以得到a[i]所属于的桶,然后对每个桶里面的少量元素排序,最后将所有桶区间的结果按照顺序合并起来,就可以得到排序结果。这里就不放置代码了,放置一个原理图可能更能说明问题:

posted @ 2014-01-06 20:33  Tiancai Ye  阅读(172)  评论(0)    收藏  举报