例子场景
A班有5名学生,本次英文考试的成绩分别是:
- Alice: 5分
- Bourne: 3分
- Claire: 5分
- Diana: 2分
- Emily: 8分
考试分数的范围是[0,10]分,现在需要对他们的分数进行升序/降序排序。
代码实现
#include <stdio.h>
#include <stdlib.h>
int main()
{
//把要排序的分数放入数组中
int scoreArray[5] = {5,3,5,2,8};
int bucket[11]; //定义桶
int i, j; //定义两个for循环用的临时变量
for(i=0; i<=10; i++) { //初始化"桶"
bucket[i] = 0;
}
for(i=0; i<5; i++) { //把要排序的分数放入桶中
bucket[scoreArray[i]]++;
}
//开始排序
printf("升序排序\n");
for(i=0; i<=10; i++) {
for(j=1; j<=bucket[i]; j++) {
printf("%d", i);
}
}
printf("\n降序排序\n");
for(i=10; i>=0; i--) {
for(j=1; j<=bucket[i]; j++) {
printf("%d", i);
}
}
return 0;
}
算法分析
桶排序的关键在于定义”桶数组”。英文考试成绩只可能是0–>10分,共11个数字。所以需要定义的桶数组长度是11,即bucket[11]。
第二步是把5个学生的分数放入桶中,这样,桶数组的下标index表示分数,而桶数组元素的值表示该分数出现的次数。
最后,只要打印按照升序或者降序的方式打印桶数组的下标即可!特别注意printf()外层的两个for循环,这种写法比较诡异,初次看时我都看晕了…
时间复杂度
第17行for执行了M次(M=桶的个数),第21行for执行了N次(N=要排序的分数个数),第27行执行了M次,第28行执行了N次。因此该算法的时间复杂度是O(M+N+M+N),即O(2*(M+N))。我们在说时间复杂度的时候可以忽略较小的常数,最终桶排序的时间复杂度为O(M+N)。
优点缺点
桶排序是一种用空间换时间的排序方法。它的优点是排序速度非常快,但是它常占用空间。如果你需要拍排序的数字范围是[0,1000000000],则你必须要初始化一个长度为1000000001的数组。
另外,这个简化版的桶排序仅仅把分数进行了排序。最终的输出结果也仅仅是分数,但没有对人本身进行排序。也就是说,我们现在并不知道排序后的分数原本对应着哪一个人。