排序算法-桶排序20220411

桶排序思想和计数排序比较相似,不同的是桶排序支持小数排序,为了支持小数排序,桶排序在操作的时候,为待排序数组构建一个List,而这个List的每个元素又是一个List,这每个List元素各自管理一段数值区间,当进行桶排序的时候,遍历待排序数组,将每个数放到对应的数值区间中,就像丢到不同的桶里一样,最后再对每个桶进行内部排序,最后遍历整个List,最终得到排序数组。

首先需要知道每个区间跨度多少合适,使用公式(最大值 - 最小值)/(桶数量 - 1)计算,这里桶数量等于待排序数组元素个数。
而每个元素应该放到哪个桶里,这里进行一个简单的公式推导:

  1. 设应该放到哪个桶为x,区间跨度为y,即将放入的元素为a,桶数量为b,数组最大值为max,最小值为min。
  2. 得到公式:y * x > a - min >= y * (x - 1)
  3. 对2.公式变形,得到 x > (a - min) / y >= x - 1
  4. 鉴于排序中并没有其他地方用到这个区间跨度变量,故将区间跨度公式代入整理后最终得到:
    x > (a - min) * (b - 1) / (max - min) >= x - 1。

通过上面得到的公式,用最懒的强转int会舍掉小数后面所有值特性,直接得到桶的index,也就是那个x - 1。
桶排序代码如下:

public static double[] bucketSort(double[] array) {
		//得到数列的最大值和最小值,并算出差值d
		double max = array[0];
		double min = array[0];
		for (int i = 1; i < array.length; i++) {
			if (array[i] > max) {
				max = array[i];
			}
			if (array[i] < min) {
				min = array[i];
			}
		}
		double d = max - min;
		//初始化桶
		int bucketNum = array.length;
		ArrayList<LinkedList<Double>> bucketList = new ArrayList<>(bucketNum);
		for (int i = 0; i < bucketNum; i++) {
			bucketList.add(new LinkedList<>());
		}
		//遍历原始数组,将每个元素放入桶中
		for (double v : array) {
			int num = (int) ((v - min) * (bucketNum - 1) / d);
			bucketList.get(num).add(v);
		}
		//对每个桶内部进行排序
		for (LinkedList<Double> doubles : bucketList) {
			//JDK 底层采用了归并排序或归并的优化版本
			Collections.sort(doubles);
		}
		//输出全部元素
		double[] sortedArray = new double[array.length];
		int index = 0;
		for (LinkedList<Double> list : bucketList) {
			for (double element : list) {
				sortedArray[index] = element;
				index++;
			}
		}
		return sortedArray;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值