算法与数据结构07:计数排序与桶排序

发布于:2022-07-24 ⋅ 阅读:(173) ⋅ 点赞:(0)

算法与数据结构07:计数排序与桶排序

计数排序

/**
 * 计数排序
 */
public class CountSort01 {

    public static void sort(int[] arr) {
        if (arr == null || arr.length < 2) return;

        //找出数组中最大的数
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            max = Math.max(arr[i], max);
        }

        //创建一个辅助数组
        int[] help = new int[max + 1];

        //遍历待排序的数组,值作为help数组的下标,help数组中的值+1
        for (int i = 0; i < arr.length; i++) {
            help[arr[i]]++;
        }

        //根据help数组,把数拷贝回原数组
        int index = 0;
        for (int i = 0; i < help.length; i++) {
            for (int j = 0; j < help[i]; j++) {
                arr[index++] = i;
            }
        }

    }

}

桶排序

/**
 * 桶排序:计数排序的一种应用
 */
public class CountSort02 {

    public static void sort(int[] arr) {
        if (arr == null || arr.length < 2) return;

        //取得当前数组最大值的位数
        int maxBit = getMaxBit(arr);

        //创建一个辅助数组
        int[] help = new int[arr.length];

        for (int i = 1; i <= maxBit; i++) {

            int[] count = new int[10];

            for (int j = 0; j < arr.length; j++) {
                //获取数组中每个值指定位上的数
                int bitNum = getBitNum(arr[j], i);
                //count数组此时记录指定数位上不同数字出现的次数
                count[bitNum]++;
            }

            for (int j = 1; j < count.length; j++) {
                //count数组变成指定数位上数字小于等于j的数的个数有几个
                count[j] += count[j - 1];
            }

            //根据count数组的记录,从原数组的最后一位往前遍历,放入help数组中的指定位置
            for (int j = arr.length - 1; j >= 0; j--) {
                int bitNum = getBitNum(arr[j], i);
                //count[bitNum]记录了当前数位i上数字小于等于bitNum的数,出现的次数
                //所以arr[j]放入到help数组中count[bitNum]-1的位置
                help[count[bitNum] - 1] = arr[j];
                //处理过了,减一,下次遇到指定数位上数字相同的数,就会放到前一个位置
                count[bitNum]--;
            }

            //help数组拷贝回原数组
            for (int j = 0; j < help.length; j++) {
                arr[j] = help[j];
            }

        }

    }

    private static int getBitNum(int num, int bit) {
        for (int i = 0; i < bit - 1; i++) {
            num /= 10;
        }
        int help = (num / 10) * 10;
        return num - help;
    }

    private static int getMaxBit(int[] arr) {
        //找出数组中最大的数
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            max = Math.max(arr[i], max);
        }

        int res = 0;
        while (max != 0) {
            max /= 10;
            res++;
        }

        return res;
    }

}

桶排序是计数排序的一种应用。从低数位开始直到高数位,每次遍历数组中的每一个数,以对应数位上的数作为下标,把当前数放入到该下标指定的队列中,然后在遍历每一个队列,弹出放回到原数组。
可以做出如下优化:
1、假设当前数位为d
2、遍历数组每一个数的d数位上的数,创建一个count数组,下标为d,记录d数位上的数出现的次数,count[i]此时就是d数位上的数位i的出现了几次
3、遍历count数组,累加前缀和,count[i]就是d数位上的数小于等于i的,出现了几次
4、创建一个help数组,从后往前遍历原数组,得出d数位上的数i,然后根据count[i]得知,d数位上的数小于等于i的有count[i]个,则在数组help下标为count[i]-1的位置放入当前遍历的数,然后count[i]减一,表示d数位上的数小于等于i的还剩count[i]-1个没处理


网站公告

今日签到

点亮在社区的每一天
去签到