十大排序算法之四 - 计数排序

十大排序算法之四 - 计数排序

1.计数排序的介绍

  • 计数排序,这种排序算法是利用数组下标来确定元素的正确位置的
  • 假设数组中有10个整数,取值范围为0~10,要求用最快的速度把这10个整数从小到大进行排序,可以根据这有限的范围,建立一个长度为11的数组。数组下标从0到10,元素初始值全为0
    在这里插入图片描述
  • 假设数组数据为:9,1,2,7,8,1,3,6,5,3
  • 下面就开始遍历这个无序的随机数列,每一个整数按照其值对号入座,同时,对应数组下标的元素进行加1操作
    在这里插入图片描述
  • 该数组中每一个下标位置的值代表数列中对应整数出现的次数
  • 计数排序:适合于连续的取值范围不大的数组,不连续和取值范围过大会造成数组过大
  • 如果起始数不是从0开始,比如分数排序:95,94,91,98,99,90,99,93,91,92,数组起始数为90,这样数组前面的位置就浪费了,可以采用偏移量的方式:

2.Java实现计数排序

(此处内部实现查找最小值(小顶堆实现),进行偏移,然后再进行计数排序,从而为用户节省了一部分操作)

package com.lagou.calculateSort;

import java.util.Arrays;

/**
 * @author 云梦归遥
 * @date 2022/5/18 10:55
 * @description 计数排序
 */
public class CalculateSortMethod {
    // 计数排序
    public int[] calculateSort(int[] array){
        int length = array.length; // 记录数组长度
        // 将原数组复制一份构建小顶堆
        int[] arrayCopy = new int[length];
        System.arraycopy(array, 0, arrayCopy, 0, length);
        int min = min(arrayCopy); // 获取小顶堆堆顶(数组最小元素)

        // 构建计数数组,用于记录各个数的数量
        int[] arrayCount = new int[length];
        for (int i = 0; i < length; i++){
            arrayCount[array[i] - min]++;
        }

        // 用于构建结果数组
        int[] arrayResult = new int[length];
        for (int i = 0, index = 0; i < length; i++){
            for (int j = 0; j < arrayCount[i]; j++){
                arrayResult[index++] = min + i;
            }
        }
        return arrayResult;
    }

    // 获取数组中的最小值
    private int min(int[] array){
        for (int i = array.length / 2 - 1; i >= 0; i--){
            createHeapMinSort(array, i, array.length);
        }
        // 返回第一个数据就是最小的树
        return array[0];
    }

    // 通过小顶堆实现寻找数组中的最小值,实现偏移存储
    private void createHeapMinSort(int[] array, int parent, int length){
        for (int i = parent * 2 + 1; i < length; i = i * 2 + 1){
            // 左节点大于右节点,以右节点来判断
            if (i + 1 < length && array[i] > array[i + 1]){
                i++;
            }
            if (array[parent] > array[i]){
                int temp = array[i];
                array[i] = array[parent];
                array[parent] = temp;
                // 将子节点作为父节点继续向下构建小顶堆
                parent = i;
            } else {
                // 下面已经是小顶堆了
                break;
            }
        }
    }
}

进行测试

package com.lagou.calculateSort.test;

import com.lagou.calculateSort.CalculateSortMethod;

import java.util.Arrays;

/**
 * @author 云梦归遥
 * @date 2022/5/18 11:26
 * @description
 */
public class CalculateSortMethodTest {
    public static void main(String[] args) {
        CalculateSortMethod calculateSortMethod = new CalculateSortMethod();
        int[] array = {3, 2, 5, 7, 4, 1, 9, 6, 8};
        System.out.println("【计数排序 - 前】" + Arrays.toString(array));
        int[] sort = calculateSortMethod.calculateSort(array);
        System.out.println("【计数排序 - 后】" + Arrays.toString(sort));
    }
}

在这里插入图片描述

3.总结

  • 计数排序的时间复杂度是O(n)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值