【重温基础算法】内部排序之计数排序法

内部排序之计数排序法

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

主要思想

  1. 计算待排序数组的数据范围(最大值+1)作为计数数组的长度:或者为了降低空间占用量,可以用最大最小的差值+1作为数组长度。例如待排序数据组的最大值是18,最小值是6,那么计数数组的长度就是(18-6+1=13)。
  2. 遍历待排序数组,计算每个元素出现的个数,将结果存放到计数数组,以(元素值-待排序数组最小值)作为下标位置。待排序数组的第1个元素值为4,计算4在待排序数组中出现的次数1,结果存放到计数数组,以(4-1=3)作为下标位置。
  3. 遍历计算数组,从第二个值开始向后进行累加操作,累加规则a[i]=a[i-1]+a[i]。
  4. 反向填充排序数组,遍历待排序数组,获取待排序数据中的每一个元素值,以这个元素值作为下标,获取计数数组中的元素值,这个元素值就是待排数据在已排序数组中的下标位置,排序后对计数数组中的元素值进行-1操作。比如待排序数组的第1个元素值为4,获取计数数组下标为4的元素值为6,那么待排数据4在已排序的数组的下标就是6,在对计数数组进行中6进行-1,此时计数数组下标4的元素值就是5。

过程演示

【重温基础算法】内部排序之计数排序法_第1张图片

java实现

package sort;

/**
 * 计数排序
 */
public class CountingSort {
    public static void main(String[] args) {
        int[] o = {7, 6, 9, 3, 1, 5, 2, 4, 8};
        System.out.print("排序前: ");
        for (int t : o) {
            System.out.print(t);
            System.out.print(" ");
        }
        System.out.println();

        // 算法部分
        int maxValue = getMaxValue(o);
        int bucketLen = maxValue + 1;
        int[] bucket = new int[bucketLen];

        for (int value : o) {
            bucket[value]++;
        }

        int sortedIndex = 0;
        for (int j = 0; j < bucketLen; j++) {
            while (bucket[j] > 0) {
                o[sortedIndex++] = j;
                bucket[j]--;
            }
        }

        System.out.print("排序后: ");
        for (int t : o) {
            System.out.print(t);
            System.out.print(" ");
        }
        System.out.println();

    }

    private static int getMaxValue(int[] arr) {
        int maxValue = arr[0];
        for (int value : arr) {
            if (maxValue < value) {
                maxValue = value;
            }
        }
        return maxValue;
    }
}

执行结果

排序前: 7 6 9 3 1 7 2 4 8 
排序后: 1 2 3 4 6 7 7 8 9 

算法分析

时间复杂度

待排序的元素的数据范围为 C C C(常数),待排序的元素个数是 N N N个。计数排序不是比较排序,它只是去访问了每个元素一下,这样时间复杂度就是 O ( C + N ) = O ( N ) O(C+N)=O(N) O(C+N)=O(N)

空间复杂度

由于我们申请了大小为 N N N 的计数数组来放元素,所以空间复杂度是 O ( N ) O(N) O(N)

你可能感兴趣的