标签:
之前总结了基于比较模型的常见排序算法,它们中最快的也要消耗O(nlogn)时间。但是我们应该知道的是,在一定条件下以线性时间进行排序依然是可能的。桶式排序和基数排序在合适的条件下就是以线性时间执行的算法。
桶式排序(bucket sort):
思想:如果我们限制需要排序的整数的范围,比如说我们有n个整数,范围从0到m-1,我们可以利用这个信息得到一种快速的排序算法。我们留置一个数组,称之为t,大小为m,并初始化为0。于是t有m个单元(桶),开始时它们都是空的。当i被读入时t[i]加一。在所有的输入被读进之后,扫描数组t,打印输出排好序的表到原数组。
void bucket_sort(int a[],int n,int m) { int *t, i, j = 0; t = (int *)malloc(m * sizeof(int)); for (i = 0; i < m; i++) t[i] = 0; for (i = 0; i < n; i++) t[a[i]]++; for (i = 0; i < m; i++) while (t[i]-- > 0) a[j++] = i; free(t); }
初始化t数组费时θ(m),扫描数组a费时θ(n),再扫描数组t费时θ(m),其他操作θ(1),加起来得θ(m+n),如果m=θ(n),则桶式排序为θ(n)。
基数排序(radix sort):
基数排序是桶式排序的推广,基数排序也被称为卡式排序(card sort),因为直到现代计算机出现以前,它一直用于对老式穿孔机的排序。
思想:如果数的范围太大,用桶式排序是不现实的,因为需要的桶太多。人们的策略是使用多趟桶式排序。一种正确的算法是用最低位优先的方式进行桶式排序。不同于桶式排序,此时可能会出现多个数落在一个桶里的情况,那么这种情况下我们就不能再使用一维数组了。如果使用二维数组的话,每个数组必然大小为n,总的空间需求将是θ(n^2)。我们可以考虑用链表的方式实现基数排序。首先创立10个表头,分别记录0,1,2,3...9,并建立从0到1到2到9的链接。第一趟排序依据个位上的数将元素加入相应的表头。第二趟排序从0到9扫描10个表头,考察表头连接的元素的十位,将元素链接到相应表头的链表后。第三遍考察百位...依次下去,直到所有元素都被插入到0表头之后,遍历0表头,依次输出到原数组便完成了排序。
...说是这样说,突然犯懒了,想现在就洗澡睡觉了,明天再贴代码吧。
标签:
原文地址:http://www.cnblogs.com/evilkant/p/5774762.html