桶排序

一)算法介绍

桶排序也可称为箱排序,是计数排序的升级版。

工作原理:把数据平均分布到有限数量的桶中,再对每一个桶中的数据分别排序(对桶中数据排序是可选的,看具体情况)。

优势:它利用了函数的映射关系,减少了数据的比较操作,效率取决于映射函数。

 

二)算法原理

基本原理

第一步:声明有限数量的桶,如:纯数字可以申请10个桶,纯字母可以申请26个桶。桶的数量是自定义,主要是方便计算。

第二步:编写一个映射函数,把数据一个个均匀分配到每个桶中。

第三步:由于数据会有大小的差异,所以需要分别对每个桶的数据再进行排序(排序方式可自选)。

第四步:把已排好序的数据从桶中一个个复制到源数据中。

 

备注:对桶中的数据排序操作,(第三步)不一定是必须的。如只统计每个桶中数量的情况下。

例如:统计全国高考每一科目,分数在0到150分,分别各有多少人,假设不存在小数的情况,只需要声明151个桶,把数据均匀分配到每一个桶中,再计算每个桶中的数量,即可得出结果。

 

算法步骤图解

 

源数据:double[] nums = {44.12, 34.12, 45.99, 23.65, 34.05, 98.99, 45.33, 12.43, 98.67, 11.66};

第一步、由于数字只有0到9共10个数,申请10个桶。

第二步、根据映射函数计算元素需要分配到那一个桶中。计算方式:int index = ((int)data)%10;

第三步、数据有大小差异,在分配到桶中的时候,需要再对桶中的数据进行排序(如插入排序)。

第四步、把已排好序的数据复制到源数据中,完成排序。

 

算法排序效果图:

 

算法复杂度:

最差情况:T(n) = O(n^2)

最好情况:T(n) = O(n+k)

// O(n^2)含义
for(i=0;i<100;i++) {
    for(i=0;i<100;i++){
    }
}

 

三)算法源码

步骤简介:先声明有限数量个桶,按照映射函数把数据一个个均匀分配到每一个桶中,再对每一个桶中数据进行插入排序,最后把已排好序的数据重新复制到源数据中。

/**
 * 桶排序
 * @param nums
 * @return
 */
public static double[] bucketSort(double[] nums) {
	if (nums == null) {
	    return null;
	}
		
	// 由于数字只有0到9总共10个数字,所以声明10个桶
	ArrayList<LinkedList<Double>> buckets = new ArrayList<LinkedList<Double>>();
	for (int i=0; i<10; i++) {
		buckets.add(new LinkedList<Double>());
	}
		
	for (double data : nums) {
		int index = ((int)data)%10; // 映射函数
			
		insertionSort(buckets.get(index), data); // 每一个桶的元素排列可能不一直,需要单独对桶中的元素再进行排序
	}
		
	// 把已排好序的数据复制到源数据中
	int index = 0;
	for (LinkedList<Double> bucket : buckets) {
		for (double data : bucket) {
			nums[index++] = data;
		}
	}
		
	return nums;
}
	
/**
 * 插入排序
 * @param bucket
 * @param data
 */
public static void insertionSort(LinkedList<Double> bucket, double data) {
	ListIterator<Double> iterator = bucket.listIterator();
		
	boolean flag = true; // 标识是否已经排序
	while (iterator.hasNext()) {
		if(data <= iterator.next()) {
			iterator.previous(); // 上移一个位置
			iterator.add(data);
			flag = false;
			break;
		}
	}
		
	if(flag) {
		bucket.add(data);
	}
}

 

识别二维码关注个人微信公众号

本章完结,待续,欢迎转载!
 
本文说明:该文章属于原创,如需转载,请标明文章转载来源!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值