控件中国网现已改版,您看到的是老版本网站的镜像,系统正在为您跳转到新网站首页,请稍候.......
中国最专业的商业控件资讯网产品咨询电话:023-67870900 023-67871946
产品咨询EMAIL:SALES@COMPONENTCN.COM

三大线性排序之桶排序

作者:未知 出处:cnblog 2013年07月26日 阅读:

 一.概念引入

 
        有作者把计数排序也称为桶排序(各个桶中元素的排序采用计数排序),得到数组C后直接从前往后遍历,输出数组值次数组下标,为0就不输出(或者存入原数组,不稳定),不过笔者认为这种说法不严谨(一个很明显的问题是输出会是双重for循环,不过也有那个意思,叫鸽巢排序也未尝不可),因为桶排序要求输入数据在[0,1)范围内(计数排序要求整数),先把区间[0,1)划分成n个相同大小的子区间,称为桶,然后将n个输入数分布到各个桶中去。因为输入数均匀且独立分布在[0,1)上,所以,一般不会有很多数落在一个桶中的情况。为了得到结果,先对各个桶中的数进行排序,然后按次序把各桶中的元素列出来。
 
        附上鸽巢排序核心源代码:
 
 
public void pigeonSort(int[] array, int max) {  
    int[] c = new int[max];//max是array数组中的最大值
    for(int i=0; i<array.length; i++)   
        c[array[i]]++;  
    //c数组只是统计元素出现次数
    int k = 0;
    for(int i=0; i<max; i++)   
        for(int j=1; j<=c[i]; j++)  
            array[k++] = i;  
}
 
二.算法描述
 
        例如要对大小为[1..1000]范围内的n个整数A[1..n]排序,可以把桶设为大小为10的范围,具体而言,设集合B[1]存储[1..10]的整数,集合B[2]存储(10..20]的整数,……集合B[i]存储((i-1)*10, i*10]的整数,i = 1,2,..100。总共有100个桶。然后对A[1..n]从头到尾扫描一遍,把每个A[i]放入对应的桶B[j]中。 然后再对这100个桶中每个桶里的数字排序,这时可用冒泡,选择,乃至快排,一般来说任何排序法都可以。最后依次输出每个桶里面的数字,且每个桶中的数字从小到大输出,这样就得到所有数字排好序的一个序列了。 
 
        下图表示出了桶排序作用于有10个数的输入数组上的操作过程。
 
 
 
三.算法的Java实现
 
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
 
public class BucketSort {
 
    public static void bucketSort(double array[]) {
        int length = array.length;
        ArrayList arrList[] = new ArrayList[length];
        /*
         *  每个桶是一个list,存放落在此桶上的元素
         *  上次的基数排序我采用的是计数排序实现的,其实也可以用下面的方法,有兴趣的读者不妨一试(我认为太复杂)
         *  不过效率估计不高(采用了动态数组)
         */
        //划分桶并填元素
        for (int i = 0; i < length; i++) {
            //0.7到0.79放在第8个桶里,编号7;第一个桶放0到0.09
            int temp = (int) Math.floor(10 * array[i]);
            if (null == arrList[temp])
                arrList[temp] = new ArrayList();
            arrList[temp].add(array[i]);
        }
        // 对每个桶中的数进行插入排序
        for (int i = 0; i < length; i++) {
            if (null != arrList[i]) {
                //此处排序方法不定,不过越快越好,除了三大线性排序外,都没有Collections
                //和Arrays里的sort好,因为这是调优后的快拍
                //Arrays里也有,在基数排序里用过copyOf和fill方法
                Collections.sort(arrList[i]);
            }
                
        }
        //输出类似鸽巢排序
        int count = 0;
        for (int i = 0; i < length; i++) {
            if (null != arrList[i]) {
                Iterator iter = arrList[i].iterator();
                while (iter.hasNext()) {
                    Double d = (Double) iter.next();
                    array[count] = d;
                    count++;
                }
            }
        }
    }
 
    /*
     * 每个元素满足0<=array[i]<1,貌似还要长度相同,
     * 若是相同小数位(digit),则可以把小数搞为整数,最后再除以10^digit
     *  可以Random.nextInt(101)/100
     */
    public static void main(String[] args) {
        double array[] = { 0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12,
                0.23, 0.68 };
        bucketSort(array);
        for (int i = 0; i < array.length; i++)
            System.out.print(array[i] + " ");
        System.out.println();
    }
}
四.算法应用
 
        在面试的海量数据处理题目中,如对每天数以亿计的数据进行排序,直接排序即使采用nlgn的算法,依然是一件很恐怖的事情,内存也无法容纳如此多的数据,这时桶排序就可以有效地降低数据的数量级,再对降低了数量级的数据进行排序,可以得到比较良好的效果。另外也有说桶排序对元组排序,个人认为还是基数排序处理元组比较好,毕竟本身就是多关键字排序,只需要把比较单个数字(有兴趣的参看我的这一篇《基于计数排序的基数排序》http://www.cnblogs.com/hxsyl/p/3210647.html)换成比较单个元组元素就好。
 

热推产品

  • ActiveReport... 强大的.NET报表设计、浏览、打印、转换控件,可以同时用于WindowsForms谀坔攀戀Forms平台下......
  • AnyChart AnyChart使你可以创建出绚丽的交互式的Flash和HTML5的图表和仪表控件。可以用于仪表盘的创......
首页 | 新闻中心 | 产品中心 | 技术文档 | 友情连接 | 关于磐岩 | 技术支持中心 | 联系我们 | 帮助中心 Copyright-2006 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 电话:023 - 67870900 传真:023 - 67870270 产品咨询:sales@componentcn.com 渝ICP备12000264号 法律顾问:元炳律师事务所 重庆市江北区塔坪36号维丰创意绿苑A座28-5 邮编:400020
在线客服
在线客服系统
在线客服
在线客服系统