基本排序算法--计数排序随笔

基本思想

计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 [1] 当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序;其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
【适用于特定问题,也就是对源数据有要求:适用于要排序的数组大,但是数组取值区间小的 数组】

JAVA代码实现
/**
 * 计数排序【桶排序思想】
 * 计数排序是非比较排序
 * 适用于特定问题,也就是对源数据有要求
 *
 * 时间复杂度:n+k 空间复杂度:n+k
 *
 * 适用于要排序的数组大,但是数组取值区间小的 数组
 * 例如: 某员工过万的员工年龄排序 ;高考排名
 */
public class CountSort extends Sort {

    public static void main(String[] args) {
        CountSort cs = new CountSort();
        int[] arr = new int[]{2, 4, 2, 3, 7, 5, 6, 9, 8, 5, 7, 4, 9};
        arr = cs.sortTwo(arr);
        cs.print(arr);
        System.out.println();

//        DataCheck.checkArithmetic(new CountSort());
    }

    @Override
    public int[] sort(int[] arr) {
        return sortTwo(arr);
    }

    public int[] sortTwo(int[] arr){
        int[] border = findBorder(arr);
        int min = border[0];
        int count = border[1] - border[0] + 1;
        int[] barrel = new int[count];
        int[] source = new int[arr.length];

        for(int i = 0; i < arr.length; i++){
            barrel[arr[i] - min]++;
        }
        //保证稳定性
        //累加 获取排序好后 相同元素的最大索引位置+1   从右向左遍历时 保证有序
        for(int j = 1; j < barrel.length; j++){
            barrel[j] = barrel[j] + barrel[j - 1];
        }
        /*
            从右到左排序原有的 数组
            2, 4, 2, 3, 7, 1, 1, 0, 0, 5, 6, 9, 8, 5, 7, 4, 0, 9
            3 2 2 1 2 2 1 2 1 2
            3 5 7 8 10 12 13 15 16 18
            0 0 0 1 1 2 2 3 4 4 5 5 6 7 7 8 9 9
            arr[k] - min: arr[k] 元素在 barrel桶数组中的位置为 arr[k] - min
            --barrel[arr[k] - min]: 为 元素的索引位置 同时也是排序好后的结果元素位置
            排序时 每排序一个 索引位置向前移动一个单元【即减一】
         */
        for(int k = arr.length - 1; k >= 0; k--){
            source[--barrel[arr[k] - min]] = arr[k];
        }
        return  source;
    }

    public int[] sortOne(int[] arr){
        int[] border = findBorder(arr);
        int min = border[0];
        int count = border[1] - border[0] + 1;
        int[] barrel = new int[count];

        for(int i = 0; i < arr.length; i++){
            barrel[arr[i] - min]++;
        }

        return garrelToArr(barrel, arr.length, min);
    }

    public int[] sortBase(int[] arr){
        int[] source = new int[arr.length];
        int count = findMax(arr) + 1;
        int[] barrel = new int[count];

        for(int i = 0; i < arr.length; i++){
            barrel[arr[i]]++;
        }

        int index = 0;
        for(int j = 0; j < barrel.length; j++){
            while (barrel[j]-- > 0){
                source[index++] = j;
            }
        }

        return source;
    }

    // 将桶数组 转化为 排序好的结果
    public int[] garrelToArr(int[] barrel, int length, int min){
        int[] source = new int[length];
        int index = 0;
        for(int i = 0; i < barrel.length; i++){
            while (barrel[i]-- > 0){
                source[index++] = min + i;
            }
        }
        return  source;
    }

    public int[] findBorder(int[] arr){
        int[] border = new int[]{arr[0], arr[0]};
        for(int i : arr){
            if(i < border[0]){
                border[0] = i;
            }
            if(i > border[1]){
                border[1] = i;
            }
        }
        return border;
    }

    public int findMax(int[] arr){
        int max = 0;
        for(int i : arr){
            max = i > max ? i : max;
        }
        return max;
    }

    //替换
    public void swap(int[] arr, int i, int j){
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    //打印int数组
    public void print(int[] arr){
        for(int i = 0; i < arr.length; i++){
            System.out.print(arr[i] + " ");
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值