十大排序算法——桶排序

桶排序是计数排序的升级版。通过“分配”和“收集”过程来实现排序,分治思想。

原理∶设计k个桶( bucket )(编号O~k-1),然后将n个输入数分布到各个桶中去,对各个桶中的数进行排序,然后按照次序把各个桶中的元素列出来即可。

适用范围:均匀分配

第一种写法:

public class BucketSort {
    public static void main(String[] args) {
        int[] arr = {18, 11, 28, 45, 23, 50};
        int[] res = bucketSort(arr);
        for (int i = 0; i < res.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
    public static int[] bucketSort(int[] arr){
 
        // 计算最大值与最小值
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        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<ArrayList<Integer>>(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));
        }
 
        // 将桶中的元素赋值到原序列
        int index = 0;
        for(int i = 0; i < bucketArr.size(); i++){
            for(int j = 0; j < bucketArr.get(i).size(); j++){
                arr[index++] = bucketArr.get(i).get(j);
            }
        }
        return arr;
    }
}

第二种写法:

public class BucketSort {
 
    static final int DEFAULT_INITIAL_CAPACITY = 10; // 默认 10,这里具体看你的数据的量
 
    private static void bucketSort(int[] arr) {
        // 新建一个桶的集合
        ArrayList<LinkedList<Integer>> buckets = new ArrayList<LinkedList<Integer>>();
        for (int i = 0; i < DEFAULT_INITIAL_CAPACITY; i++) {
            // 新建一个桶,并将其添加到桶的集合中去。
            // 由于桶内元素会频繁的插入,所以选择 LinkedList 作为桶的数据结构
            buckets.add(new LinkedList<Integer>());
        }
        // 将输入数据全部放入桶中并完成排序
        for (Integer data : arr) {
            int index = getBucketIndex(data);
            insertSort(buckets.get(index), data);
        }
        // 将桶中元素全部取出来并放入 arr 中输出
        int index = 0;
        for (LinkedList<Integer> bucket : buckets) {
            for (Integer data : bucket) {
                arr[index++] = data;
            }
        }
    }
    /**
     * 我们选择插入排序作为桶内元素排序的方法 每当有一个新元素到来时,我们都调用该方法将其插入到恰当的位置
     * @param bucket
     * @param data
     */
    private static void insertSort(LinkedList<Integer> bucket, Integer data) {
        ListIterator<Integer> iterator = bucket.listIterator();
        boolean insertFlag = true;
        while (iterator.hasNext()) {
            if (data <= iterator.next()) {
                iterator.previous(); // 把迭代器的位置偏移回上一个位置
                iterator.add(data); // 把数据插入到迭代器的当前位置
                insertFlag = false;
                break;
            }
        }
        if (insertFlag) {
            bucket.add(data); // 否则把数据插入到链表末端
        }
    }
    /**
     * 计算得到输入元素应该放到哪个桶内
     * @param data
     * @return
     */
    private static int getBucketIndex(Integer data) {
        // 这里例子写的比较简单,仅使用对10取整作为其桶的索引值
        // 实际开发中需要根据场景具体设计
        return data / DEFAULT_INITIAL_CAPACITY;
    }
    public static void main(String[] args) {
        int[] arr = {1,28,29,3,21,11,7,6,18};
        bucketSort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

时间复杂度:时间复杂度:O(N + C)

上一篇:TreeMap集合


下一篇:日志文件管理者:Logrotate