Java数据结构与算法(排序)——桶排序

一、算法思想

通过遍历,将待排序序列分到有限数量的桶中,然后对每个桶单独进行排序,最后将所有桶的结果输出,即为有序序列(关键问题在于,如何设置合适数量的桶)。

二、算法步骤

(1)设定合适数量的桶;
(2)遍历待排序序列,将每个元素放到对应的桶中;
(3)对每个桶(非空的桶)进行合适的排序算法;
(4)按顺序访问桶,将桶中的元素依次输出,得到有序序列(注意:对每个桶使用的排序算法要与访问桶的顺序一致,比如都为从小到大)。

三、代码实现

1、简单分桶

适合于待排序序列各元素之间的大小跨度比较小的情况:

  • 桶的数目 bucketNum = max / 10 - min / 10 + 1;
  • 依据(array[i] - min)/ 10的结果将各元素放入对应的桶中;
  • 遍历所有桶,输出有序序列。

代码如下:

// 简单分桶
public int[] bucketSort1(int[] sourceArray) {
	// 拷贝数组
	int[] array = Arrays.copyOf(sourceArray, sourceArray.length);
	// 找到数组中的最大、最小值,以设定合适数量的桶
	int max = array[0];
	int min = array[0];
	for (int i = 1; i < array.length; i++) {
		if (max < array[i])
			max = array[i];
		if (min > array[i])
			min = array[i];
	}
	// 1、设定分桶情况
	int bucketNum = max / 10 - min / 10 + 1;
	List<List<Integer>> bucketList = new ArrayList<>();
	// 2、创建桶
	for (int i = 0; i < bucketNum; i++) {
		bucketList.add(new ArrayList<Integer>());
	}
	// 3、将待排序数组的元素添加到对应的桶里
	for (int i = 0; i < array.length; i++) {
		int index = (array[i] - min) / 10;
		bucketList.get(index).add(array[i]);
	}
	// 4、对每个桶进行插入排序,并把排好序的结果重新放回原数组
	List<Integer> tempBucket = null;
	int index = 0;
	for (int i = 0; i < bucketNum; i++) {
		tempBucket = bucketList.get(i);
		int[] temp = new int[tempBucket.size()];
		for(int j = 0; j < tempBucket.size(); j++){
			temp[j] = tempBucket.get(j);
		}
		temp = insertSort(temp);// 插入排序
		for(int a : temp){
			array[index++] = a;
		}
	}
	return array;
}

2、归约化分桶

适合于待排序序列各元素之间的大小跨度比较大的情况:

  • 分桶情况:index = (array[i] - min) / (max - min) * array.length;
  • 采用 HashMap 记录桶的情况:HashMap<Integer, ArrayList< Integer > > bucketMap = new HashMap<>()。遍历待排序序列,将所有元素进行上式处理,得到的 index 作为 key,对应的元素添加到动态数组中作为 value。

代码如下:

// 归约化分桶
public int[] bucketSort2(int[] sourceArray) {
	// 拷贝数组
	int[] array = Arrays.copyOf(sourceArray, sourceArray.length);
	// 找到数组中的最大、最小值,以设定合适数量的桶
	int max = array[0];
	int min = array[0];
	for (int i = 1; i < array.length; i++) {
		if (max < array[i])
			max = array[i];
		if (min > array[i])
			min = array[i];
	}
	// 1、设定分桶情况,将待排序数组的元素添加到对应的桶里
	HashMap<Integer, ArrayList<Integer>> bucketMap = new HashMap<>();
	for (int i = 0; i < array.length; i++) {
		int index = (array[i] - min) / (max - min) * array.length;
		// Map中不包含index,则为其创建list并添加至Map中
		if(!bucketMap.containsKey(index)){
			ArrayList<Integer> list = new ArrayList<>();
			list.add(array[i]);
			bucketMap.put(index, list);
		}else{// Map中已有index,则直接将该元素添加至对应的list中
			bucketMap.get(index).add(array[i]);
		}
	}
	// 2、对每个桶进行插入排序,并把排好序的结果重新放回原数组
	ArrayList<Integer> tempBucket = null;
	int index = 0;
	Iterator iterKey = bucketMap.keySet().iterator();
	while(iterKey.hasNext()){
		tempBucket = bucketMap.get(iterKey.next());
		int[] temp = new int[tempBucket.size()];
		for(int j = 0; j < tempBucket.size(); j++){
			temp[j] = tempBucket.get(j);
		}
		temp = insertSort(temp);// 插入排序
		for(int a : temp){
			array[index++] = a;
		}
	}
	return array;
}

附:插入排序

public int[] insertSort(int[] SourceArray){
	int[] array = Arrays.copyOf(SourceArray, SourceArray.length);
	// 将array[0]看做有序序列
	for (int i = 1; i < array.length; i++) {
		// 记录要插入的数据
		int temp = array[i];
		// 从已经排序的序列的最右边开始比较,找到比其小的数
		int j = i;
		// temp > array[j - 1]:大的往前走,降序
		// temp < array[j - 1]:小的往前走,升序
		while(j > 0 && temp > array[j - 1]){
			array[j] = array[j - 1];
			j--;
		}
		// 存在比其小的数,插入
		if(j != i)
			array[j] = temp;
	}
	return array;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值