鸽巢排序,只能对非负整数进行排序,是一种时间复杂度为O(N + n)其中N为最大值与最小值的差值,且在不可避免遍历每一个元素并且排序的情况下效率最好的一种排序算法。但它只有在差值(或者可被映射在差值)很小的范围内的数值排序的情况下实用。自我感觉鸽巢排序与计数排序的前几步较为相似。
我们一般很少使用鸽巢排序,因为它很少可以在灵活性,简便性,尤是速度上超过其他排序算法。
鸽巢排序
鸽巢排序,顾名思义就是把每一个值当做一个鸽巢,而一个鸽巢记录的就是a数组中每个数出现的次数,这里就用nest来记录了,nest[i]表示i这个数在a数组中出现的次数,而根据a数组计算得出这个nest数组是极为简单的。只要从1到n扫一个遍,每次让nest[a[i]]++就计算出nest数组了。
最后再从a_min到a_max遍历一遍,如果nest[i]大于0,就让数组a中从(当前有序数列的末位 + 1)到(当前有序数列的末位 + nest[i] + 1)的所有值等于i就好了,这样就顺利地将数组a排好序了。
(PS:NR是指a数组元素个数的上限,MR是a数组中最大值的上限,既nest数组的上限)
# include <cstdio>
# include <iostream>
# include <cmath>
# include <cstring>
# include <algorithm>
# include <climits>
using namespace std;
# define FOR(i, a, b) for(int i = a; i <= b; i++)
# define _FOR(i, a, b) for(int i = a; i >= b; i--)
const int NR = 100000, MR = 1000000;
int n;
int a[NR + 10];
int nest[MR + 10];
int main()
{
scanf("%d", &n);
int a_max = 0, a_min = INT_MAX;
FOR(i, 1, n){
scanf("%d", &a[i]);
a_max = max(a[i], a_max);
a_min = min(a[i], a_min);
nest[a[i]]++;
}
int now = 0;
FOR(i, a_min, a_max)
while(nest[i]--) a[++now] = i;
FOR(i, 1, n) printf("%d ", a[i]);
puts("");
return 0;
}
God Bless You For Ever!