子区间为1的简化版桶排序——计数排序
定义
简化版桶排序是指对0~n范围进行排序时,需要定义n个桶,每个桶对应一种元素或一个范围内的元素,再进行元素个数的存储,因为实质上存储的是元素个数,所以无须进行元素的比较替换,时间复杂度是O(N)
概念图
代码
源代码如下,揣摩不同的 "i "代表着什么
/********************************************************************** 实现简单的桶排序存五个人的信息 输入: 5 3 5 2 8 输出: 8 5 5 3 2 **********************************************************************/ #include<stdio.h> int main() { int a[11]; int i,j; int num; //初始化 for(i=0;i<11;i++) { a[i]=0; } //输入 for(i=0;i<5;i++) { scanf("%d",&num); a[num]++; } //输出 for(i=10;i>0;i--) { if(a[i]!=0) { for(j=0;j<a[i];j++) { printf("%3d",i); } } } printf("\n"); system("pause"); return 0; }
代码图解:
利与弊
桶排序利用函数的映射关系,减少了几乎所有的比较工作。实际上,桶排序的f(k)值的计算,其作用就相当于快排中划分,已经把大量数据分割成了基本有序的数据块(桶)。然后只需要对桶中的少量数据做先进的比较排序即可。
对N个关键字进行桶排序的时间复杂度分为两个部分:
(1) 循环计算每个关键字的桶映射函数,这个时间复杂度是O(N)。
(2) 利用先进的比较排序算法对每个桶内的所有数据进行排序,其时间复杂度为 ∑ O(Ni*logNi) 。其中Ni 为第i个桶的数据量。
很显然,第(2)部分是桶排序性能好坏的决定因素。尽量减少桶内数据的数量是提高效率的唯一办法(因为基于比较排序的最好平均时间复杂度只能达到O(N*logN)了)。因此,我们需要尽量做到下面两点:
(1) 映射函数f(k)能够将N个数据平均的分配到M个桶中,这样每个桶就有[N/M]个数据量。
(2) 尽量的增大桶的数量。极限情况下每个桶只能得到一个数据,这样就完全避开了桶内数据的“比较”排序操作。 当然,做到这一点很不容易,数据量巨大的情况下,f(k)函数会使得桶集合的数量巨大,空间浪费严重。这就是一个时间代价和空间代价的权衡问题了
————全心全意投入,拒绝画地为牢