排序算法(7): 桶排序(Bucket Sort)

2,195 阅读2分钟

基本思想

原理是将数组分到有限数量的桶子里。每个桶子再个别排序(有可能再使用别的排序算法或以递归方式继续使用桶排序进行排序)。桶排序是鸽巢排序的一种归纳结果。当要被排序的数组内的数值均匀分配的时候,桶排序使用线性时间O(n)。但桶排序并不是比较排序,他不受到O(nlogn)下限的影响。

算法描述

  • 设置一个定量的数组当作空桶
  • 遍历输入数据,并且把数据一个一个放到对应的桶里去
  • 对每个不是空的桶进行排序
  • 从不是空的桶里把排好序的数据拼接起来

演示

代码实现

	public static void sort(int[] array) {
		// 最大值
		int max = array[0];
		for (int i = 1; i < array.length; i++) {
			if (array[i] > max) {
				max = array[i];
			}
		}
		// 最大位数
		int maxLen = Integer.toString(max).length();

		// 十个桶,每个桶最多能放排序数组
		int[][] s = new int[10][array.length];

		// 记录每个桶放了多少数据
		int[] k = new int[10];

		for (int m = 0; m < maxLen; m++) {
			for (int i = 0; i < array.length; i++) {
				int mod = array[i] / (int) (Math.pow(10D, Double.valueOf(m + ""))) % 10;// 获取个位数
				s[mod][k[mod]] = array[i];
				k[mod] = k[mod] + 1;
			}
			int index = 0;
			for (int i = 0; i < 10; i++) {
				if (k[i] > 0) {
					for (int j = 0; j < k[i]; j++) {
						array[index++] = s[i][j];
					}
				}
			}
			k = new int[10];
		}
	}

时间复杂度

N个数据平均的分配到M个桶中,这样每个桶就有[N/M]个数据量
桶排序平均时间复杂度为:O(N)+O(M*(N/M)log(N/M))=O(N+N(logN-logM))=O(N+NlogN-NlogM)
当N=M时,即极限情况下每个桶只有一个数据时。桶排序的最好效率能够达到O(N)。
最佳情况:O(N) 最佳情况:O(n^2) 平均情况:O(N+C),其中C=N(logN-logM)*

空间复杂度

O(m) m在这里表示最大值

优点与缺点

  • 优点:实现简单,排序速度快于任何比较排序
  • 缺点:不稳定,只适用于小整数的排序

测试记录

待补充

源码

暂时未发现在开源框架或jdk中用到插入排序

基数排序,计数排序和桶排序

  1. 都是非比较的排序算法
  2. 基数排序和计数排序都可以看作是桶排序。计数排序本质上是一种特殊的桶排序,当桶的个数取最大的时候,就变成了计数排序。
  3. 基数排序也是一种桶排序。桶排序是按值区间划分桶,基数排序是按位数划分;基数排序可以看作是多轮桶排序,每个数位上都进行一轮桶排序。
  4. 当用最大值作为基数时,基数排序就退化成了计数排序。