zoukankan      html  css  js  c++  java
  • 看我桶排序,怎么可以更好呢

    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));
    		
    	}
    }
    
    
    所有文章未特殊说明均属原创,有误之处欢迎提出,转载随意,您喜欢就好,但请注明,谢谢!
  • 相关阅读:
    poj 2485 Highways 最小生成树
    hdu 3415 Max Sum of MaxKsubsequence
    poj 3026 Borg Maze
    poj 2823 Sliding Window 单调队列
    poj 1258 AgriNet
    hdu 1045 Fire Net (二分图匹配)
    poj 1789 Truck History MST(最小生成树)
    fafu 1181 割点
    减肥瘦身健康秘方
    人生的问题
  • 原文地址:https://www.cnblogs.com/nonefly/p/4833277.html
Copyright © 2011-2022 走看看