java桶排序

一、原理

    桶排序的工作原理是把[0,1)区间划分为n个大小相同的子区间,这样的区间称为桶。然后将n个输入的数分发到各个桶中去。每个桶再个别的排序,然后按照次序把各个桶。

二、代码

方法一计数法:计数排序需要占用大量空间,它仅适用于数据比较集中的情况。

思想是:开辟和待排序数组最大值长度+1长度的计数数组,数组有多长,桶就有多少个,将相同的放到同一个桶里面。把 arr[i] 放到它输出数组中的位置上。

例如:a = {2,  8,  6,2}; 因为a[0] = 2,所以在buckets的第2个位置对应的零加一,即将buckets[2]的值+1。

public class BucketSort {

    private int[] buckets; //桶用来记录元素值及次数
    private int[] array;

    public BucketSort(int range, int[] array){
        this.buckets = new int[range];
        this.array = array;
    }

    /**
     * 排序
     */
    public void sort(){
        if(array != null && array.length > 1) {
            for(int i = 0 ; i < array.length ; i++) {//把数组遍历一遍
                buckets[array[i]]++;//将数组每个位置出现的数值的次数、位置记录下来,arr对应数字是多少就将它放到对应buckets的位置
            }
        }
    }

    /**
     * 排序输出
     */
    public void sortOut(){
        for (int i = 0; i < buckets.length; i++){//buckets的每一项对应的就是数组中数值大小,所以i就是arr[x]
            for(int j = 0 ; j < buckets[i] ; j++){//buckets[i]对应的就是出现相同的次数
                System.out.print(i + "  ");
            }
        }
    }

    public static void main(String[] args){
        int[] array = {5, 7, 8, 10, 4, 8, 6, 4, 8, 0};
        //取出最大值
        int max = Integer.MIN_VALUE;
        for(int i = 0; i < array.length; i++){
            max = Math.max(max, array[i]);
        }
        //最坏情况下最小值是0 ,最大值是max。
        //假如最大值是10,那么此时应该需要一个长度为max+1的bucket数组去装出现次数的值,才能保证不溢出。因为数组是从零开始的到10,一共11个数字。
        int length = max + 1;
        BucketSort bs = new BucketSort(length, array);
        bs.sort();
        bs.sortOut();//输出
    }

}

分析:如果说最大值跟最小值相差不多,而且数值很大的情况下,只用max+1来作为数组长度是有些浪费和不严谨的。所以我们需要优化一下。优化后的是稳定的排序,相同的数值顺序不变。具体如下图所示:

 

优化后代码:

public class BucketSort3 {

    public static int[] countSort(int[] array) {
        //1.得到数列的最大值和最小值,并算出差值d
        //取出最大值、最小值
        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;
        for(int i = 0 ; i < array.length ; i++){//数值数组a
            max = Math.max(max, array[i]);
            min = Math.min(min, array[i]);
        }
        int d = max - min;

        //2.创建统计数组并统计对应元素个数
        int[] countArray = new int[d+1];//取最大,最小值算出差值因为数组是从零开始的,所以要装差值加一个数字
        for(int i = 0 ; i < array.length ; i++) {
            countArray[array[i] - min]++;
        }
        //3.统计数组做变形,后面的元素等于前面的元素之和
        int sum = 0;
        for(int i = 0; i < countArray.length ; i++) {//计数数组b
            //90-90 = 0 -》0(sum = 0)+1(c[0]出现一次) = 1(sum),
            // 1 + 0 (91并未出现 ——》0)        c[1] = 1,
            // 1 + 0(92并未出现 ——》0)         c[2] = 1,
            // 1 + 1(93出现 ——》1) = 2         c[3] = 2,
            // 2 + 0(94未出现 ——》0) = 2       c[4] = 2,
            // 2 + 0(95未出现 ——》0) = 2       c[5] = 2,
            // 2 + 0(96未出现 ——》0) = 2       c[6] = 2,
            // 2 + 0(97未出现 ——》0) = 2       c[7] = 2,
            // 2 + 2(98出现 ——》2) = 4         c[8] = 4,
            // 4 + 1(99出现 ——》1) = 2         c[9] = 5,
            sum += countArray[i];
            countArray[i] = sum;
        }
        //4.倒序遍历原始数列,从统计数组找到正确位置,输出到结果数组
        int[] sortedArray = new int[array.length];//排序数组c
        for(int i = array.length - 1;i >= 0;i--) {
            //每次循环计数会对应减一
            //array[4] = 98 - 90 = 8 -》c[8] = 4 -> sortedArray[3] = 98
            //array[3] = 99 - 90 = 9 -》c[9] = 5 -> sortedArray[4] = 99
            //array[2] = 93 - 90 = 3 -》c[3] = 2 -> sortedArray[1] = 93
            //array[1] = 98 - 90 = 8 -》c[8] = 3 -> sortedArray[2] = 98
            //array[0] = 90 - 90 = 0 -》c[0] = 1 -> sortedArray[0] = 90
            sortedArray[countArray[array[i] - min] - 1] = array[i];
            countArray[array[i] - min]--;//并且把对应位置的计数减一因为已经排好一个了
        }
        //sortedArray[0] = 90 ->  sortedArray[1] = 93 -> 
        // sortedArray[2] = 98 -> sortedArray[3] = 98 -> 
        // sortedArray[4] = 99
        return sortedArray;
       
    }
    public static void main(String[] args) {
        int[] array = new int[] {90,98,93,99,98};
        int[] sortedArray = countSort(array);
        System.out.println(Arrays.toString(sortedArray));
    }
}

方法二 桶排序:可用于最大最小值相差较大的数据情况,要求数据的分布必须均匀,否则可能导致数据都集中到一个桶中。

public class BucketSort2 {

    public static void 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<>(bucketNum);
        for(int i = 0; i < bucketNum; i++){
            bucketArr.add(new ArrayList<>());
        }

        //将每个元素放入桶
        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));
        }
        System.out.println(bucketArr.toString());
    }

    public static void main(String[] args){
        int[] array = {11, 6, 4, 1, 2, 3, 7, 9, 10};
        bucketSort(array);
    }
}

未完待续----------------

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
桶排序和计数排序是两种不同的排序算法。 桶排序的基本思想是将数组分到有限数量的桶里,再对每个桶中的元素进行排序,最后按照桶的顺序将元素依次列出来,形成有序序列。桶排序的时间复杂度取决于对每个非空桶进行排序时所选择的排序算法。当要排序的数据均匀分布时,桶排序可以达到线性时间复杂度。 计数排序是一种记录数据出现次数的排序算法。它的原理类似于桶排序,可以看作是一种特殊的桶排序算法。计数排序遍历序列,并将每个元素放入对应的桶中。然后按照桶的顺序将元素依次放回原来的序列中。计数排序是一种稳定的排序算法,适用于数据范围较小的情况。 对于Java语言,你可以使用以下代码实现桶排序和计数排序: 桶排序Java实现代码示例: ``` public void bucketSort(int[] arr, int bucketSize) { if (arr.length == 0) { return; } // 寻找数组的最大值和最小值 int min = arr[0], max = arr[0]; for (int i = 1; i < arr.length; i++) { if (arr[i] < min) { min = arr[i]; } else if (arr[i] > max) { max = arr[i]; } } // 桶的数量 int bucketCount = (max - min) / bucketSize + 1; List<List<Integer>> buckets = new ArrayList<>(); for (int i = 0; i < bucketCount; i++) { buckets.add(new ArrayList<>()); } // 将数组中的元素放入对应的桶中 for (int i = 0; i < arr.length; i++) { int bucketIndex = (arr[i] - min) / bucketSize; buckets.get(bucketIndex).add(arr[i]); } // 对每个桶中的元素进行排序,并放回原来的序列中 int index = 0; for (int i = 0; i < bucketCount; i++) { List<Integer> bucket = buckets.get(i); Collections.sort(bucket); for (int j = 0; j < bucket.size(); j++) { arr[index++] = bucket.get(j); } } } ``` 计数排序的Java实现代码示例: ``` public void countingSort(int[] arr) { if (arr.length == 0) { return; } // 寻找数组的最大值和最小值 int min = arr[0], max = arr[0]; for (int i = 1; i < arr.length; i++) { if (arr[i] < min) { min = arr[i]; } else if (arr[i] > max) { max = arr[i]; } } // 计算数组中每个元素的出现次数 int[] counts = new int[max - min + 1]; for (int i = 0; i < arr.length; i++) { counts[arr[i] - min]++; } // 将计数数组中的元素依次放回原来的序列中 int index = 0; for (int i = 0; i < counts.length; i++) { while (counts[i] > 0) { arr[index++] = i + min; counts[i]--; } } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值