排序算法--------计数排序和桶排序

计数排序和桶排序

目录

计数排序和桶排序

1、计数排序

1.1 算法描述

1.2 动图演示

2.3 算法性能分析

2.4 算法实现

2.5 算法的优化

2、桶排序

2.1 算法思想

2.2 图解

2.3 算法性能分析

2.4 算法实现


1、计数排序

计数排序是一种非比较性质的排序算法元素从未排序状态变为已排序状态的过程,是由额外空间的辅助和元素本身的值决定的。计数排序过程中不存在元素之间的比较和交换操作,根据元素本身的值,将每个元素出现的次数记录到辅助空间后,通过对辅助空间内数据的计算,即可确定每一个元素最终的位置。

1.1 算法描述

  • 找出待排序的数组中最大和最小的元素
  • 统计数组中每个值为i的元素出现的次数,存入数组C的第i项
  • 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
  • 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。

例如:

待排序集合:[3, -1, 2, 3, 1]

(1)序列中最大值为:3,最小值为-1:,根据序列中最大值和最小值的差值范围5,可得申请额外空间大小为5

(2)按要求放入数据

       (3)遍历数组,回填。

1.2 动图演示

2.3 算法性能分析

算法 最好时间 最坏时间 平均时间 额外空间 稳定性
计数排序 O(n + k) O(n + k) O(n + k) k 稳定

2.4 算法实现


/**
 * 计数排序
 */
public class CountSort {
    public static void sort(int[] nums){
        if(nums == null || nums.length == 0)
            return;
        int mix = nums[0];
        int max = nums[0];
        for(int i = 0; i < nums.length; ++i){ //查找数组最大和最小值
            if(nums[i] < mix)
                mix = nums[i];
            if(nums[i] > max)
                max = nums[i];
        }
        int[] tmep = new int[max - mix + 1];  //创建辅助数组
        for(int i = 0; i < nums.length; ++i){
            tmep[nums[i] - mix]++;
        }
        int index = 0;
        int flag = 0;
        while(index < nums.length){     //从辅助数组中按顺序读取
            if(tmep[flag] != 0){
                nums[index++] = flag + mix;
                tmep[flag]--;
            }else{
                flag++;
            }
        }
    }
    public static void main(String args[]){
        int[] nums = new int[]{-1,-5,6,9,4,-2,12,11,-6};
        CountSort.sort(nums);
        for(int num : nums){
            System.out.print(num + "    ");
        }
    }
}

    运行结果:

-6    -5    -2    -1    4    6    9    11    12

2.5 算法的优化

优化思路:利用数据挖掘对序列进行简单的数据归约,根据归约后映射的值把序列分治为比较均匀的序列,再使用计数排序对子序列进行排序,从而在保证时间效率的情况下减少了空间的分配。

例如:输入{10, 32, 14, 34, 56, 10000028, 10000034, 10000037, 10000089, 10000023},最小值是10,最大值是10000089,数组的长度是10,最大值、最小值的差为10000079

      可以把序列划分为两个子序列{10,32,14,34,56},{10000028, 10000034, 10000037, 10000089, 10000023}


2、桶排序

桶排序是将待排序集合中处于同一个值域的元素存入同一个桶中,也就是根据元素值特性将集合拆分为多个区域,则拆分后形成的多个桶,从值域上看是处于有序状态的。对每个桶中元素进行排序,则所有桶中元素构成的集合是已排序的。

快速排序是将集合拆分为两个值域,这里称为两个桶,再分别对两个桶进行排序,最终完成排序。桶排序则是将集合拆分为多个桶,对每个桶进行排序,则完成排序过程。两者不同之处在于,快排是在集合本身上进行排序,属于原地排序方式,且对每个桶的排序方式也是快排。桶排序则是提供了额外的操作空间,在额外空间上对桶进行排序,避免了构成桶过程的元素比较和交换操作,同时可以自主选择恰当的排序算法对桶进行排序。

当然桶排序更是对计数排序的改进,计数排序申请的额外空间跨度从最小元素值到最大元素值,若待排序集合中元素不是依次递增的,则必然有空间浪费情况。桶排序则是弱化了这种浪费情况,将最小值到最大值之间的每一个位置申请空间,更新为最小值到最大值之间每一个固定区域申请空间,尽量减少了元素值大小不连续情况下的空间浪费情况。

2.1 算法思想

  1. 根据待排序集合中最大元素和最小元素的差值范围和映射规则,确定申请的桶个数;
  2. 遍历待排序集合,将每一个元素移动到对应的桶中;
  3. 对每一个桶中元素进行排序,并移动到已排序集合中。

步骤 3 中提到的已排序集合,和步骤 1、2 中的待排序集合是同一个集合。与计数排序不同,桶排序的步骤 2 完成之后,所有元素都处于桶中,并且对桶中元素排序后,移动元素过程中不再依赖原始集合,所以可以将桶中元素移动回原始集合即可

2.2 图解

2.3 算法性能分析

算法 平均时间 最优时间 最坏时间 额外空间 稳定性
简单选择排序 O(n + k) O(n + k) O(n2) n + k 稳定

2.4 算法实现

/**
     * 桶排序
     * 
     * @param array
     * @param bucketSize
     * @return
     */
    public static ArrayList<Integer> BucketSort(ArrayList<Integer> array, int bucketSize) {
        if (array == null || array.size() < 2)
            return array;
        int max = array.get(0), min = array.get(0);
        // 找到最大值最小值
        for (int i = 0; i < array.size(); i++) {
            if (array.get(i) > max)
                max = array.get(i);
            if (array.get(i) < min)
                min = array.get(i);
        }
        int bucketCount = (max - min) / bucketSize + 1;
        ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketCount);
        ArrayList<Integer> resultArr = new ArrayList<>();
        for (int i = 0; i < bucketCount; i++) {
            bucketArr.add(new ArrayList<Integer>());
        }
        for (int i = 0; i < array.size(); i++) {
            bucketArr.get((array.get(i) - min) / bucketSize).add(array.get(i));
        }
        for (int i = 0; i < bucketCount; i++) {
            if (bucketSize == 1) { // 如果带排序数组中有重复数字时  
                for (int j = 0; j < bucketArr.get(i).size(); j++)
                    resultArr.add(bucketArr.get(i).get(j));
            } else {
                if (bucketCount == 1)
                    bucketSize--;
                ArrayList<Integer> temp = BucketSort(bucketArr.get(i), bucketSize);
                for (int j = 0; j < temp.size(); j++)
                    resultArr.add(temp.get(j));
            }
        }
        return resultArr;
    }

参考:

https://www.cnblogs.com/guoyaohua/p/8600214.html

发布了78 篇原创文章 · 获赞 53 · 访问量 8150

猜你喜欢

转载自blog.csdn.net/qqq3117004957/article/details/104954643
今日推荐