桶排序

桶排序的原理和计数排序类似,可以说是计数排序的升级版。他利用了函数映射关系,将输入的值映射到对应的桶里面去。

所以他的高效就在于这个映射函数的确定。所以需要做到如下两点:

1.在额外空间充足的情况下,尽量增大桶的数量。

2.使用映射函数能将输入的N个数据均匀的分配到K个桶中去。

此外就是对于桶中的数据元素的排序时,使用哪种比较排序的算法比较好,对性能的影响至关重要。

什么时候最快:

当输入数据可以均匀分配到每一个桶中去.

什么时候最慢:

当输入数据分配到一个桶中去.

分析过程(图片部分制作粗糙,请见谅):

根据最大值最小值分配的给这个桶切块。切成的块是23然后通过每个数字去计算这个放到那个模块中。我这里只展示这几个数据的各部分。我们将桶的size设置为了5,也就是说每个桶只能放入5个数据元素。

也可以理解为将根据间隔为5,用数轴依次展开,就可以直到这个数大致位于哪里了。

(这里没有对倒数第二个桶进行内部排序)


参考代码:

使用的是插入排序。

public class BucketSort {

	public static void main(String[] args) {
		int [] a = {121, 39, 56, 20, 9, 7, 16};
		System.out.println(Arrays.toString(bucketSort(a, 5)));
	}

	private static int[] bucketSort(int[] arr, int bucketSize) {

		//arr复制
		int[] a = Arrays.copyOf(arr, arr.length);
		//寻找最大值和最小值
		int max = a[0];
		int min = a[0];
		for(int i = 0; i < a.length; i ++){
			if(a[i] > max){
				max = a[i];
			}
			else if(a[i] < min){
				min = a[i];
			}
		}
		//math.floor()对浮点数向下取整
		int bucketCount = (int)Math.floor((max - min) / bucketSize) + 1;
		int [][] buckets = new int[bucketCount][0];
		//通过映射函数将各数据映射到桶中去
		for(int i = 0; i < a.length; i ++){
			int index = (int)Math.floor((a[i] - min) / bucketSize);
			buckets[index] = arrApend(buckets[index], a[i]);
		}
		int arrIndex = 0;
		for(int[] bucket : buckets){
			if(bucket.length <= 0){//招那些装了数据的桶
				continue;
			}
			//对每个桶进行排序, 使用插入排序
			bucket = insertSort(bucket);
			for(int value : bucket){
				a[arrIndex ++] = value;
			}
		}
		return a;
	}

	private static int[] arrApend(int[] array, int value) {

		array = Arrays.copyOf(array, array.length + 1);
		array[array.length - 1] = value;
		return array;
	}

	//插入排序  -- 一个标志位  和之前的所有元素比较
	private static int[] insertSort(int [] a){
		int temp = 0;
		int j = 0;
		for(int i = 1; i < a.length; i ++){
			temp = a[i];
			for(j = i; j > 0 && a[j - 1] > temp; j --){
				a[j] = a[j - 1];
			}
			a[j] = temp;
		}
		return a;
	}
}

输出的时候是根据桶的顺序输出数据。

结果截图:




以上就是这篇的内容,如果有什么错误或者可以改进的地方,亦或是你有什么疑惑,欢迎留言。让我们共同进步。谢谢!

阅读更多
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页