排序算法之桶排序【Java版】

引言

本篇是排序算法的第八篇,桶排序,桶排序是计数排序的升级版。

1、算法步骤

1、设定一个基准,将待排序的数字按照一定范围,从小到大的平均分在N个桶中,此时桶已经排好序,桶中的元素还未排序;
2、将桶中的元素进行排序。
3、将每个桶按照从小到大的编号,依次取出里面的元素放入到待排序数组中,排序完成。

2、时间复杂度

平均时间复杂度O(n + k)

3、算法实现

public class BucketSort {
    
    

    public static void main(String[] args) {
    
    
        int[] numbers = {
    
    12,2,24,30,6,16};
        int[] result = BucketSort.bucketSort(numbers,3);
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < result.length; i++) {
    
    
            stringBuffer.append(result[i] + " ");
        }
        System.out.println(stringBuffer.toString());
    }

    //bucketSize是初始化桶个数的一个基准值
    public static int[] bucketSort(int[] arg,int bucketSize){
    
    
        if(arg.length == 0){
    
    
            return arg;
        }
        int maxValue = arg[0];
        int minVaule = arg[0];
        for (int i = 1; i < arg.length; i++) {
    
    
            if(arg[i] < minVaule){
    
    
                minVaule = arg[i];
            } else if(arg[i] > maxValue){
    
    
                maxValue = arg[i];
            }
        }
        //桶的数量
        int bucketCount = (int)Math.floor((maxValue - minVaule) / bucketSize) + 1;
        //初始化一个二维数组,横坐标是桶的编号,纵坐标是值
        int[][] buckets = new int[bucketCount][0];
        //将待排序值按照一定规则映射到数组中
        for (int i = 0; i < arg.length; i++) {
    
    
            int index = (int)Math.floor((arg[i] - minVaule) / bucketSize);
            buckets[index] = arrAppend(buckets[index], arg[i]);
        }
        int arrIndex = 0;
        //循环每个桶
        for (int i = 0; i < buckets.length; i++) {
    
    
            if(buckets[i].length <= 0){
    
    
                continue;
            }
            //将每个桶中的数组按照插入排序算法进行排序
            int[] bucket = insertSort(buckets[i]);
            //按照桶的顺序,将桶中排好序的值,依次放入到数组中
            for (int j = 0; j < bucket.length; j++) {
    
    
                arg[arrIndex++] = bucket[j];
            }
        }
        return arg;
    }
    //插入排序算法
    public static int[] insertSort(int[] arr){
    
    
        for (int i = 1; i < arr.length; i++) {
    
    
            // 记录要插入的数据
            int tmp = arr[i];
            // 从已经排序的序列最右边的开始比较,找到比其小的数
            int j = i;
            while (j > 0 && tmp < arr[j - 1]) {
    
    
                arr[j] = arr[j - 1];
                j--;
            }
            // 存在比其小的数,插入
            if (j != i) {
    
    
                arr[j] = tmp;
            }
        }
        return arr;
    }
    //自动扩容,并保存数据
    public static int[] arrAppend(int[] arr,int value){
    
    
        arr = Arrays.copyOf(arr, arr.length + 1);
        arr[arr.length - 1] = value;
        return arr;
    }
}

结束语

桶排序的高效与否的关键就在于这个映射函数的确定,在空间足够的时候,尽量增加桶的数量,将数据尽量均匀的分到K个桶中。

猜你喜欢

转载自blog.csdn.net/cool_summer_moon/article/details/106919993