持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情
计数排序
流程
定义大小为待排数组大小的数组b[]桶,统计元素中各个元素出现的次数。最后遍历整个桶,该元素出现几次就输出几次,完成排序。(狭义桶排序)该算法对输入数据要求较大,我们需要定义b[max(a[])+1]大小的数组,所以就对输入元素进行了限制。
演示
依次输入:3 5 4 1 2 3
| 编号 | 执行操作前的b[] | 操作 |
|---|---|---|
| 0. | 0 0 0 0 0 0 | 输入3,b[3]++。 |
| 1. | 0 0 0 1 0 0 | 输入5,b[5]++。 |
| 2. | 0 0 0 1 0 1 | 输入4,b[4]++。 |
| 3. | 0 0 0 1 1 1 | 输入1,b[1]++。 |
| 4. | 0 1 0 1 1 1 | 输入2,b[2]++。 |
| 5. | 0 1 1 1 1 1 | 输入3,b[3]++。 |
| 6. | 0 1 1 2 1 1 | 遍历b数组,输出b[i]个i |
| 8. | 输出结果:1 2 3 3 4 5 |
代码
#include <stdio.h>
#define N 1000001
int n,a[N]={0},x;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&x),a[x]++;
for (int i=0;i<N;++i)
for (int j=1;j<=a[i];++j) printf("%d ",i);
return 0;
}
时间复杂度
O(max(N,max{a})。
桶排序
介绍
桶排序又称箱排序,是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值是均匀分配的时候,桶排序使用线性时间。但桶排序并不是比较排序,他不受到 O(nlogn) 下限的影响。
流程
先使用范围的计数排序将数据分类,再继续用桶排序或者使用其他排序方式对桶内数据进行排序。
时间复杂度
桶排序利用函数的映射关系,减少了比较工作,把大量数据分割成了基本有序的数据块(桶)。然后只需要对桶中的少量数据进行排序即可。
对N个关键字进行桶排序的时间复杂度分为两个部分:
- 循环计算每个关键字的桶映射函数,这个时间复杂度是O(N)。
- 利用先进的比较排序算法对每个桶内的所有数据进行排序。
很显然,第 2 部分是桶排序性能好坏的决定因素。因此,我们需要尽量做到下面两点:
- 映射函数f(k)能够将N个数据平均的分配到M个桶中,这样每个桶就有[N/M]个数据量。
- 尽量的增大桶的数量,当桶的数量够多以至于每个桶中只有一个数据时,转化为计数排序。