了解更多关于nonefly,欢迎访问我的主页
nonefly
无羽的博客 随心而动+-+随梦而行
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
//桶排序
/**
 * 桶排序是用空间来换取时间,类似查表,它的时间复杂度可以突破(n log n)的下限,达到线性级别
 * 
 * 整体思想感觉特别,特别,特别!类似于构建hash表
 * @author nonefly
 * 2015年9月20日
 */
public class Bucket {

	/**
	 * 其一种,如果排序的数字差距(MAX-MIN)不是很大,比如录入成绩全是[0-100]的,
	 * 或者数据分布都在一个范围之内
	 * ==================================
	 * 待排序数组     9 8 6 5 2 2
	 *  
	 * 桶中数字     0 0 2 0 0 1 1 0 1 1  代表有几个对应下标的数          
	 * 桶下标         0 1 2 3 4 5 6 7 8 9
	 */
	private static void bucketSimpleSort(int[] a, int max){
		int[] arr = new int[max+1];//这个就是桶,就像hash时申请的一个连续数组
		
		//ai代表a数组第i个,用桶中下标为ai的数字计数a[i];
		//这步就像hash映射时的index = value % a.length;
		//因为申请的空间肯定(如上[max+1])是大于value(即max)的,
		//因此如上的hash映射也就等于index = value;
		
		for (int ai : a) {
			++arr[ai];
		}//构建桶
		//构建好的桶每一项arr[i],意思即是下标i的数据有arr[i]个
		//下标本来就是有序的,然后从桶中谢晖原数组好了
		
		for (int i = a.length - 1; i >= 0; ) {//原数组,倒着写回,可以只计算一次a.length,当然这点点优化并没有什么意思
			for (int j = max; j >= 0; j--) {//遍历桶中数据
				while(arr[j]-- > 0)//arr[j]为多少就写回几个(考虑数组中重复情况)
					a[i--] = j;
			}
		}
		//考虑分布在一段范围内情况,不是从0开始,比如[200,250]
		//那么可以分配250-200+1数量的桶
		//构建桶时a[i]-200就是对应下标
		//写回数组时下表+200就是对应的值
	}
	/**
	 * 第二种
	 * hash用链表解决碰撞的做法又[很]类似另一种桶排序的设计思路:
	 * ①用顺序表来作为桶 (同理hash中的申请的计算出hash值对应的空间)
	 * ②用链表存储同一个桶中元素(hash中用链表解决碰撞)
	 * ③同一个桶中直接插入排序(桶中不会也不应该有很多个元素,因此直接插入效率最高)
	 * ④写回(和上面的一样)
	 */
	private static void bucketSort(int[] a,int max){
		final int len = a.length;
		List<LinkedList<Integer>> bucket = new ArrayList<LinkedList<Integer>>(a.length);
		for (int i = 0; i < len; i++) {
			bucket.add(new LinkedList<Integer>());
		}//初始化桶全为空
		
		for (int i = 0; i < len; i++) {
			//忘了从哪偷来的 这种a[i] * len / (max+1)计算下标想法
			//感觉挺好用,注意max+1,这样使得最大值映射不至于越界
			//虽然也可以创建桶时多加一个位置
			List<Integer> list = bucket.get(a[i] * len / (max+1));
			int index = 0;
			while(index < list.size() && list.get(index) < a[i]) ++index;//直接插入排序
			list.add(index, a[i]);
		}//将数据按序填充到桶中
		
		//按序写会原数组中
		int backi = 0;
		for (LinkedList<Integer> linkedList : bucket) {
			for (Integer integer : linkedList) {
				a[backi++] = integer;
			}
		}
	}
	
	public static void bucketSort(int[] a){
		//排序认为都是安全数字,所以传值之前应该检验
		if(a == null || a.length < 1)
			return;
		int max = Integer.MIN_VALUE;
		for (int ai : a) {
			max = max > ai ? max : ai;
		}
		//bucketSimpleSort(a, max);//简单桶
		bucketSimpleSort(a, max);
	}
	public static void main(String[] args) {
		
		int a[] = {1,2,3,4,5,6,70,18,9,0,9,87,6,54};
		bucketSort(a);
		System.out.println(Arrays.toString(a));
		
	}
}

posted on 2015-09-23 19:13  nonefly  阅读(178)  评论(0编辑  收藏  举报