计数排序

前言

最近在学数据结构与算法,在此做一下记录,方便时不时复习一下。如果有什么做得不对的地方,恳请指出,万分感谢。

简述

计数排序是一个排序时不比较大小的排序算法。如果一个数组里所有元素都是整数,而且都在0~k以内。对于数组里的每个元素来说,如果能知道数组里有多少项小于或等于该元素,就能准确地给出该元素在排序后的数组位置。

比如下图:

对于这个数组来说,元素5之前有8个元素小于等于5(含5本身),因此排序后5所在的位置肯定是下标为7的位置。只要构造一个(5+1)大小的数组,里面存下所有对应A中每个元素之前的元素个数,就能在线性时间内完成排序。

但是在实际使用中会找出数组中的最大值(max)和最小值(min),主要是为了节省空间,比如[1004,1002,1040,1050]这样的数据要排序,真需要建立长度为1050+1的数组么?很明显是不需要滴嘛。只需要长度为1050-1004+1=47的数组(先不考虑额外+1的长度),就能囊括最小到最大元素之间的所有元素了。如果待排序数组的元素跨度很大,比如[9999,1,3],为了三个元素排序需要使用9999-1+1的空间,太浪费啦。

计数排序对一定范围内的整数排序的时候,这个排序算法速度非常快,一般快于其他排序算法。但技术排序的局限性比较大,只限于对整数进行排序,而且待排序元素值需分布较连续、跨度小。

步骤

1.找出数组的最大值和最小值;

2.对偏移量赋值offset;

3.定义计数数组并赋值;

4.计算对应计数数组下标值的原数组数值的个数;

5.定义一个数值作为原始数组下标标识index;

6.定义一个数值作为计数数组的下标标识i;

7.当index小于原始数组的长度时,如果对应i计数数组的值不为0:对应的index原始数组为i-offset,对应的i计数数组值减一,index加一;如果对应i计数数组的值为0,i++。

8.重复第7步,直到index大于原始数组长度为止,此时原数组已排序好。

图示

代码

public class CountSort {

    public final static int[] DATA = {3,5,4,0,3,4,0,4};

    public static void main(String[] args) {
        printArray(DATA);
        System.out.println("==================");
        printArray(sort(DATA));
    }

    public static int[] sort(int[] arrays) {
        if (arrays.length == 0) return arrays;
        int offset,max = arrays[0],min = arrays[0];

        //找出最大最小值,用于获取计数数组的长度
        for (int i = 0; i < arrays.length; i++) {
            if (arrays[i] > max) max = arrays[i];
            if (arrays[i] < min) min = arrays[i];
        }

        //获取偏移量
        offset = 0 - min;

        //定义计数数组,并对计数数组赋值
        int[] countArray = new int[max - min + 1];
        Arrays.fill(countArray,0);//初始化原始计数数组.全部赋值为0
        for (int i = 0; i < arrays.length; i++) {//这步就是计算对应计数数组下标值的原数组的个数
            countArray[arrays[i] + offset]++;
        }
        System.out.println("计数数组为:");
        printArray(countArray);
        System.out.println("====================");

        int index = 0;//这是用来作为原始数组下标的标识
        //这是用来作为计数数组下标的标识
//        int i = countArray.length - 1;//如果i从countArray.length - 1开始,就是降序
        int i = 0;//如果i从0开始,就是升序

        while (index < arrays.length) {
            if (countArray[i] != 0) {
                arrays[index] = i - offset;//对原数组重新赋值
                countArray[i]--;
                index++;
            }else
//                i--;//降序
            i++;//升序
            printArray(countArray);
            printArray(arrays);
            System.out.println("---------------------");
        }

        return arrays;
    }

    public static void printArray(int[] array) {
        for (int i:array) {
            System.out.print(i + " ");
        }
        System.out.println("");
    }

}

结果

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值