子区间为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)函数会使得桶集合的数量巨大,空间浪费严重。这就是一个时间代价和空间代价的权衡问题了

 

posted @ 2017-07-14 15:14  bw98  阅读(217)  评论(1编辑  收藏  举报