在信息学竞赛中,排序是一种非常非常基本的算法,甚至不能称之为算法,因为用的套多了,今天介绍三种并不是基于比较的算法,计数排序,基数排序,桶排序。
1.计数排序,
计数排序不同与快速排序或者冒泡排序,它并不是基于比较的排序,而基于比较的排序,可以证明它的时间下届是log(n!)=nlog(n);
故计数排序可以获得更好的时间复杂度,但是,计数排序对元素的大小手限制,故其实用性便大大的降低,但是在特定的算法中,巧妙的应用却能够得到很神奇的效果,如基数排序在后缀数组中的应用.
首先给定一个数组b,要求对数组b进行排序,并已知数据的范围是0到k,那么开数组c[k],下面写下伪代码:
for(i=1,i<=b.len,i++)
c【b[i]】=c[b[i]]+1;
for(i=1;i<=k;i++)
c[i]=c[i]+c[i-1];//这样c【i】表示小于等于i的数的个数有多少;
然后进行输出就可以了:
for(int j=b.len;j>=1;j--)//为什么要倒叙输出,因为要保证排序是稳定,
d[c[b[j]]]=b[j];
c[b[j]]--;
2. 桶排序
首先定义桶,桶为一个数据容器,每个桶存储一个区间内的数。依然有一个待排序的整数序列A,元素的最小值不小于0,最大值不超过K。假设我们有M个桶,第i个桶Bucket[i]存储iK/M至(i+1)K/M之间的数,有如下桶排序的一般方法:
- 扫描序列A,根据每个元素的值所属的区间,放入指定的桶中(顺序放置)。
- 对每个桶中的元素进行排序,什么排序算法都可以,例如快速排序。
- 依次收集每个桶中的元素,顺序放置到输出序列中
3.基数排序:
假设我们有一些二元组(a,b),要对它们进行以a为首要关键字,b的次要关键字的排序。我们可以先把它们先按照首要关键字排序,分成首要关键字相同的若干堆。然后,在按照次要关键值分别对每一堆进行单独排序。最后再把这些堆串连到一起,使首要关键字较小的一堆排在上面。按这种方式的基数排序称为MSD(Most Significant Dight)排序。
第二种方式是从最低有效关键字开始排序,称为LSD(Least Significant Dight)排序。首先对所有的数据按照次要关键字排序,然后对所有的数据按照首要关键字排序。要注意的是,使用的排序算法必须是稳定的,否则就会取消前一次排序的结果。由于不需要分堆对每堆单独排序,LSD方法往往比MSD简单而开销小。下文介绍的方法全部是基于LSD的。
通常,基数排序要用到计数排序或者桶排序。使用计数排序时,需要的是Order数组。使用桶排序时,可以用链表的方法直接求出排序后的顺序。
浙公网安备 33010602011771号