理解桶排序算法原理

Posted 我是攻城师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理解桶排序算法原理相关的知识,希望对你有一定的参考价值。

计数排序,基数排序,桶排序是所有排序算法里面时间复杂度能达到O(N)级别的算法,这主要原因是因为他们不采用基于比较的算法,前面的文章已经介绍了计数排序的原理,本片文章我们来学习一下桶排序(Bucket sort)算法。

桶排序的步骤是:

(1)设置一个定量桶的个数,并使用这个数初始化一个数组,元素的类型可以是链表或者数组。

(2)计算出待排序数组的最大值

(3)使用最大值除以桶的个数并向上求整,得到划分区间的divider

(4)遍历待排序数组,取每个元素除以divider并向下取整,放入对应的桶里面

(5)遍历桶数组,对每个桶进行排序,这里排序算法不限,可以采用计数排序,快排,插入都可以。

(6)最终顺序合并每个桶数组,便得到整体有序的数组。

桶排序的平均时间复杂度O(n+k),空间复杂度最快的情况下为O(n*k),桶排序适合数据分布比较均匀 的场景,即每个桶分到的元素个数相差不多,极端情况下,所有的待排序元素都一样,那么最终会分配到一个桶里面 ,此时如果还采用了基于比较的排序算法,那么最坏的时间复杂度会达到O(n^2)。

下面看下示例代码:

 
   
   
 
  1.    private static void bucketSort(){

  2.        int arr[]={1,28,29,29,289,89,30,100,43,-2,36,57,58};

  3.        int max=arr[0],min=arr[0];

  4.        for(int i:arr){

  5.            max=Math.max(max,i);

  6.            min=Math.min(min,i);

  7.        }

  8.        System.out.println("范围:["+min+"->"+max+"]");

  9.        int bucketSize=5;

  10.        int divider= (int)Math.ceil( (max+1)/bucketSize);

  11.        System.out.println(" 桶的个数:"+bucketSize+" 每个桶的范围:"+divider);

  12.        List<Integer>[] storeResults=new ArrayList[bucketSize];

  13.        for (int i = 0; i <arr.length ; i++) {

  14.              int findIndex=(int)Math.floor(arr[i]/divider);

  15.              if(storeResults[findIndex]==null){

  16.                  storeResults[findIndex]=new ArrayList<Integer>();

  17.              }

  18.              storeResults[findIndex].add(arr[i]);

  19.        }

  20.        int ndx=0;

  21.        for(List bucket:storeResults){

  22.            if(bucket==null) continue;

  23.            //每个桶的数据,可以采用不同的排序方式,这里用Java内置的集合排序

  24.            Collections.sort(bucket);

  25.            //排序完的数据,即可归并

  26.            for (Object i:bucket){

  27.                 arr[ndx]=(int)i;

  28.                 ndx++;

  29.            }

  30.        }

  31.        System.out.println("排序后:"+ Arrays.toString(arr));

  32.    }

上面的实现采用了List来存储每个桶的元素,这里还可以采用链表,这样插入的性能会更好一点,分桶完成之后,对每个桶进行排序,仅仅为了演示,我这里使用的Java的内置集合工具类来排的顺序,这块的排序算法不限制也可以采用计数排序,插入排序等。

最终在每一段排完顺序后依次合并即可,合并的时候不需要做任何额外的比较,这一点区别于归并排序。

总结:

总体来说,桶排序与计数排序类似,计数排序可以认为是分了最大数量的桶排序,而桶排序则是,将一堆数据分了固定数量的桶中,然后对每个桶的中的数据进行排序,最后合并,桶的数量会影响桶排序的性能,并不是越大越好,这个可以根据实际的数量来估算。


以上是关于理解桶排序算法原理的主要内容,如果未能解决你的问题,请参考以下文章

十大排序算法(原理及代码实现细节)

理解计数排序算法的原理和实现

桶排序原理及实现

这才是你想要桶排序

数据结构与算法桶排序

每日一算法|桶排序---第十天