排序算法-桶排序

版权声明:本文为博主原创文章,欢迎大家转载,但是要注明我的文章地址。 https://blog.csdn.net/program_developer/article/details/82753905

一、桶排序适用数据范围

桶排序可用于最大最小值相差较大的数据情况,比如[9012,19702,39867,68957,83556,102456]。但桶排序要求数据的分布必须均匀,否则可能导致数据都集中到一个桶中。比如[104,150,123,132,20000], 这种数据会导致前4个数都集中到同一个桶中。导致桶排序失效。

二、桶排序过程分析

桶排序的基本思想是:将一个数据表分割成许多个bucket(桶),然后每个bucket可以各自排序(可以采用不同的排序算法)。它是典型的分而治之的策略。

具体的算法思想:

假设有一组长度为n的待排关键字序列K[1….n]。首先将这个序列划分成M个的子区间(桶) 。然后基于某种映射函数 ,将待排序列的关键字k映射到第i个桶中(即桶数组B的下标 i) ,那么该关键字k就作为B[i]中的元素(每个桶B[i]都是一组大小为n/M的序列)。接着对每个桶B[i]中的所有元素进行比较排序(可以使用快排)。然后依次枚举输出B[0]….B[M]中的全部内容即是一个有序序列。

【桶排序关键】映射函数

index=f(key), 其中index为桶数组B的下标(即第index个桶), key为待排序列的关键字。桶排序之所以能够高效,其关键在于这个映射函数,它必须做到:如果关键字key1<key2,那么f(key1)<=f(key2)。也就是说B(i)中的最小数据都要大于B(i-1)中最大数据。很显然,映射函数的确定与数据本身的特点有很大的关系。

桶排序的动态演示:

Bucket Sort

地址:https://www.cs.usfca.edu/~galles/visualization/BucketSort.html

注意:计数排序是桶排序的一种特殊情况,可以把计数排序当成每个桶里只有一个元素的情况。

桶排序算法步骤:

1.找出待排序数组中的最大值max、最小值min
2.我们使用动态数组ArrayList 作为桶,桶里放的元素也用 ArrayList 存储。桶的数量为(max-min)/arr.length+1
3.遍历数组 arr,计算每个元素 arr[i] 放的桶
4.每个桶各自排序
5.遍历桶数组,把排序好的元素放进输出数组

三、桶排序实例

比如有数据{32, 43, 1, 65, 43, 57, 83, 93, 73, 22, 28, 53},这些数据在区间[0, 100)中,将这些数据分进十个桶中(注意:这里桶的数量是自己定义的),然后在这些桶中对其中的数据进行排序。如下图所示: 

四、桶排序代码实现

import java.util.ArrayList;
import java.util.Collections;

public class bucketSort {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] array = {32, 43, 1, 65, 43, 57, 83, 93, 73, 22, 28, 53};
		ArrayList result = BucketSort(array);
		System.out.println(result.toString());
	}
	
	public static ArrayList BucketSort(int[] arr) {
		
		int min = arr[0];
		int max = arr[0];
		for(int i=0; i<arr.length; i++) {
			max = Math.max(max, arr[i]);
			min = Math.min(min, arr[i]);
		}
		
		//桶个数
		int bucketNum = (max -min) / arr.length +1;
		//构造桶
		ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
		for(int i=0; i<bucketNum; i++) {
			bucketArr.add(new ArrayList<Integer>());
		}
		
		// 将每个元素放入桶中
		for(int i=0; i<arr.length; i++) {
			int num = (arr[i] - min) / (arr.length);
			bucketArr.get(num).add(arr[i]);
		}
		
		//对每个桶进行排序
		for(int i=0; i<bucketArr.size(); i++) {
			Collections.sort(bucketArr.get(i));
		}
		
		return bucketArr;
	}

}

五、时间复杂度和空间复杂度分析

1. 桶排序的平均时间复杂度是线性的,即O(n)。

2. 桶排序中,需要创建M个桶的额外空间,以及N个元素的额外空间。

3. 桶排序算法是稳定算法。

六、Reference

【1】https://www.cnblogs.com/zer0Black/p/6169858.html

【2】https://www.cs.usfca.edu/~galles/visualization/BucketSort.html

【3】https://blog.csdn.net/wodedipang_/article/details/63268624

【4】https://juejin.im/post/5b4f55676fb9a04fb745d0df

【5】https://blog.csdn.net/u010647471/article/details/49522603

【6】http://hxraid.iteye.com/blog/647759

猜你喜欢

转载自blog.csdn.net/program_developer/article/details/82753905