经典算法 (四) 桶排序

时隔一年,小葵花课堂再次开课,这次开课不会像之前那样很早就停课了,在此给大家道个歉:对不起。嘻嘻….又到了毕业季了,废话不多说,继续我们的算法学习。

一丶算法描述

桶排序 (Bucket sort):是一个排序算法,工作的原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序;算法时间复杂度为:O(M+N)。
举个栗子:
经典算法 (四) 桶排序_第1张图片(图片来自网络)
如图:我们要对29,25,3,49,9,37,21,43进行从小到打的排序,根据桶排序的定义,我们要把数组分成大小相等的几个桶,图中分为5个桶,每个桶的长度均为0~9。然后我们把数组里面的数分配到这5个桶里面,然后这样我们就把数据分成了5份,然后每个桶在进行排序(可以冒泡、桶等排序),最后把桶的数据拼一起就出来了最后的结果。这个图片上的算法大家在看完文章后,自己用来练习。

二算法实现

问题描述:学校要给女排运动员买运动鞋(妹子鞋子的尺码我们定义范围:30-40),然后让队长统计妹子的鞋子大小,然后按照从小到大的顺序排序,上报给学校,下面我们用这个算法来解决这个问题。

    private void bucketSort() {
        //鞋子的尺码
        int shoeSize[] = {36, 34, 40, 38, 36, 37, 38};
        //由于我们鞋子的范围是30-40,也就是我们需要11个桶,定义桶数据
        int[] arrs = new int[11];

        //初始化桶数据,
        for (int i = 0; i < arrs.length; i++) {
            arrs[i] = 0;
        }
        //把鞋子的尺码分配到桶里

        for (int i = 0; i < shoeSize.length; i++) {
            //
            int size = shoeSize[i] - 30;
            //每个尺码每出现一次,就标记一次,数量加一
            arrs[size] = arrs[size] + 1;
        }
       //依次判断arrs[0]~arrs[10]
        for (int i = 0; i < arrs.length; i++) {
            //出现几次打印几次,我们知道arrs[i]对应数据代表出现的次数。
            for (int j = 0; j < arrs[i]; j++) {
                int size = i + 30;
                Log.e("ShoeSize", "排序后顺序" + size);
            }
        }


    }

分析:上面的问题有个特殊的条件:鞋子的尺码在30至40之间(30≤size≤40),首先我们创建11个桶,为啥11个桶呢?(自己用手指头数一数就知道了),然后把每个鞋子的尺码放到size-30的桶里,为啥要减三十呢?
举个栗子,
栗子A:假设待排序的数组a中共有N个整数,并且已知数组a中数据的范围[0, MAX)。在桶排序时,创建容量为MAX的桶数组r,并将桶数组元素都初始化为0;将容量为MAX的桶数组中的每一个单元都看作一个”桶”。
在排序时,逐个遍历数组a,将数组a的值,作为”桶数组r”的下标。
尺码出现一次,标记一次,数量加一:还是继续看栗子A,当a中数据被读取时,就将桶的值加1。例如,读取到数组a[3]=5,则将r[5]的值+1。。
最后,看一下运行结果:
经典算法 (四) 桶排序_第2张图片

总结

桶排序的最优时间复杂度为O(n),最差时间复杂度取决于桶中的排序算法,所以桶的数量越多,时间效率越高,完美情况是每个桶中只有一个数据,时间复杂度可以达到O(n),但是会浪费很大的空间,考虑时间和空间的权衡问题。在数据规模合适的情况下,桶排序的表现可以优于快排等基于比较的排序算法。

你可能感兴趣的:(算法)