数据结构与算法系列十七(计数排序)

152 阅读3分钟

上一篇:数据结构与算法十六(桶排序) 中,我们知道了桶排序是一个高效的排序算法,它的时间复杂度是:O(n) 。桶排序适合于对大规模的数据量进行排序,只要满足前提条件:数据分布相对均匀,也就是说分桶后,每个桶的数据量均衡。

这一篇我们再来看另外一个高效的排序算法,它是桶排序的一个变种:计数排序,它的时间复杂度也是:O(n)

#考考你:
1.你知道计数排序实现的思想吗
2.你能用java实现计数排序吗

案例

计数排序实现思想

计数排序,是桶排序的一个特列。我们先看一个例子,只要你理解了这个例子,你也就理解了计数排序适合的场景,以及它的实现思想。

例子:

1.快要一年一度的高考了,我们以给考生考试成绩排序为例

2.假如全省有100万考生参加考试,满分是750。如何实现根据考生考试成绩进行排名

3.根据桶排序原理,以及考试分数范围:0-750。可以分751个桶

4.每个桶用于存放对应分数的考生数量。比如a[0],表示0分的考生数量

5.扫描待排序数组array[n],通过桶(计数数组)count[max-min],对每个array[n] 中出现的元素,进行计数

6.扫描计数数组count[max-min],还原数组array[n]。排序结束

这个例子不难理解,我们抓一下关键点:

#实现思想关键要点:
1.以考生的分数进行分桶,每个桶存放对应分数的考生数量;
2.扫描待排序数组array[n],统计计数每个桶(分数)对应的考生数量
3.扫描计数数组(桶),还原数组array[n]。此时array[n]中的数据,即已经按照考生分数排好序

文字描述总要差那么点感觉,大家都是程序员,直接上代码,相信你就能理解了。

计数排序代码实现

主体代码

package com.anan.algorithm.sort;

import java.util.Arrays;

/**
 * 计数排序:
 *  1.思想:
 *      1.1.计数排序,是桶排序的一个特例
 *      1.2.假如全省有100万考生参加考试,满分是750。如何实现根据考生考试成绩进行排名
 *      1.3.实现思路:
 *          1.3.1.根据桶排序原理,以及考试分数范围:0-750。可以分751个桶
 *          1.3.2.每个桶用于存放对应分数的考生数量。比如a[0],表示0分的考生数量
 *          1.3.3.这里通过数组来代表桶
 *          1.3.4.扫描待排序数组array[n],通过桶(计数数组)count[max-min],对每个array[n]
 *          中出现的元素,进行计数
 *          1.3.5.扫描计数数组count[max-min],还原数组array[n]。排序结束
 *
 *  2.时间复杂度:
 *      O(n)
 *  3.空间复杂度:
 *      O(m):m是桶的个数
 */
public class CountingSort {
    public static void main(String[] args) {
        // 1.定义待排序数组(这里假设分数范围:0-20)
        Integer[] array = {1,6,3,4,2,5,9,8,10,7,11,20,17,16,15,18,19,2,3,1,9,8,6,1,20};
        int n = array.length;
        System.out.println("1.待排序数组元素个数:" + n +",元素内容:" + Arrays.asList(array));

        // 2.定义计数数组(桶)
        Integer[] count = new Integer[21];
        for (int i = 0; i < count.length; i++) {
            count[i] = 0;
        }

        // 3.关键步骤一:计数
        //扫描待排序数组array[n],通过桶(计数数组)count[max-min],对每个array[n]中出现的元素,进行计数
        for(int i = 0; i < array.length; i++){
            count[array[i]] ++;
        }

        System.out.println("2.计数数组元素个数:" + count.length +",元素内容:" + Arrays.asList(count));

        // 4.关键步骤二:还原
        //扫描计数数组count[max-min],还原数组array[n]。排序结束
        Integer[] sortResult = new Integer[array.length];
        int k = 0;
        for (int i = 0; i < count.length; i++) {
            if(count[i] > 0){
                for (int j = 0; j < count[i]; j++) {
                    sortResult[k++] = i;
                }
            }

        }

        System.out.println("3.排序后数组元素个数:" + n +",元素内容:" + Arrays.asList(sortResult));

    }
}

image.png