算法学习记录010_基数排序

package com.study.data.structures.sort;

import java.util.Arrays;


/**
 * 基数排序
 * 所有自然数都是由0到9构成的,所以准备一个二维数组来进行数据的装填
 * 定义二维数组,
 * int[][] arr = new int[11][arr.length]
 * {43, 986, 7, 21, 591, 87}
 * <p>
 * 第一轮:
 * 依次取出待排序元素,并获取该元素的个位数放到其对应的数组中。例如:43%10=3,那么就将43放入到arr[3]
 * arr[0]={}
 * arr[1]={21,591}
 * arr[2]=
 * arr[3]={43}
 * arr[4]=
 * arr[5]=
 * arr[6]={986}
 * arr[7]={7,87}
 * arr[8]=
 * arr[9]=
 * 结果是:{21,591,43,986,7,87}
 * <p>
 * <p>
 * 第二轮:
 * 依次取出待排序元素,并获取该元素的十位数放到其对应的数组中。例如:43/10%10=4,那么就将43放入到arr[4]
 * arr[0]={7}
 * arr[1]=
 * arr[2]={21}
 * arr[3]=
 * arr[4]={43}
 * arr[5]=
 * arr[6]=
 * arr[7]=
 * arr[8]={986,87}
 * arr[9]={591}
 * 结果是:{7,21,43,986,87,591}
 * <p>
 * <p>
 * 第三轮:
 * 依次取出待排序元素,并获取该元素的十位数放到其对应的数组中。例如:43/100%10=0,那么就将43放入到arr[0]
 * arr[0]={7,21,43,87}
 * arr[1]=
 * arr[2]=
 * arr[3]=
 * arr[4]=
 * arr[5]={591}
 * arr[6]=
 * arr[7]=
 * arr[8]=
 * arr[9]={986}
 * 结果是:{7,21,43,87,591,986}
 * <p>
 * 一共循环3次,因为数组元素中最大值的位数是3位
 *
 * 当前基数排序对于负数是存在局限性的:
 * 个人认为:
 * 如果待排序数组中存在负数的话,可以在第一次基数排序时针对负数做一次收集,然后针对负数进行一次基数排序。
 * 最后按照排序规则进行所有数据的合并
 */
public class RadixSort {

    public static void main(String[] args) {
        int[] arr = {43, 986, 7, 21, 591, 87};
//        radixSortDeduction(arr);
        int[] arrays = new int[8000000];
        for (int i = 0; i < 8000000; i++) {
            arrays[i] = (int) (Math.random() * 8000000);
        }
        long startTime = System.currentTimeMillis();
        radixSort(arrays);
        long endTime = System.currentTimeMillis();
        System.out.println(endTime - startTime);
    }

    private static void radixSort(int[] arr) {
        //定义一个二维数组,使用arr.length是因为实在无法确定,每个一维数组会装多少元素,所以就去最大值
        int[][] radixTemp = new int[10][arr.length];
        //用于记录每个一维数组添加数据的个数
        int[] radixCount = new int[10];
        //先获取待排序数组中的最大数值,用以确定外层循环需要多少次
        int max = arr[0];
        for (int i = 0; i < arr.length; i++) {
            max = Math.max(max, arr[i]);
        }
        System.out.println(max+"");

        int maxLength = (max + "").length();
        int index = 0;
        for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
            for (int j = 0; j < arr.length; j++) {
                int num = arr[j];
                int digit = num / n % 10;
                //获得下标为digit的数组
                int[] currentArr = radixTemp[digit];
                //往下标为digit的数组中添加数据
                currentArr[radixCount[digit]++] = num;
            }
            index = 0;
            for (int k = 0; k < radixCount.length; k++) {
                int count = radixCount[k];
                if (count != 0) {
                    for (int g = 0; g < count; g++) {
                        arr[index++] = radixTemp[k][g];
                    }
                    radixCount[k] = 0;
                }
            }

//            System.out.println("第" + i + "轮::" + Arrays.toString(arr));
        }

    }

    private static void radixSortDeduction(int[] arr) {
        //定义一个二维数组,使用arr.length是因为实在无法确定,每个一维数组会装多少元素,所以就去最大值
        int[][] radixTemp = new int[10][arr.length];
        //用于记录每个一维数组添加数据的个数
        int[] radixCount = new int[10];
        //第一轮
        for (int i = 0; i < arr.length; i++) {
            int num = arr[i];
            int singleDigit = num % 10;
            int[] currentArr = radixTemp[singleDigit];
            currentArr[radixCount[singleDigit]++] = num;
        }
        int index = 0;
        for (int i = 0; i < radixCount.length; i++) {
            int count = radixCount[i];
            if (count != 0) {
                for (int j = 0; j < count; j++) {
                    arr[index++] = radixTemp[i][j];
                }
                radixCount[i] = 0;
            }
        }

        System.out.println("第一轮::" + Arrays.toString(arr));


        //第二轮
        for (int i = 0; i < arr.length; i++) {
            int num = arr[i];
            int singleDigit = num / 10 % 10;
            int[] currentArr = radixTemp[singleDigit];
            currentArr[radixCount[singleDigit]++] = num;
        }
        index = 0;
        for (int i = 0; i < radixCount.length; i++) {
            int count = radixCount[i];
            if (count != 0) {
                for (int j = 0; j < count; j++) {
                    arr[index++] = radixTemp[i][j];
                }
                radixCount[i] = 0;
            }
        }

        System.out.println("第二轮::" + Arrays.toString(arr));

        //第三轮
        for (int i = 0; i < arr.length; i++) {
            int num = arr[i];
            int singleDigit = num / 100 % 10;
            int[] currentArr = radixTemp[singleDigit];
            currentArr[radixCount[singleDigit]++] = num;
        }
        index = 0;
        for (int i = 0; i < radixCount.length; i++) {
            int count = radixCount[i];
            if (count != 0) {
                for (int j = 0; j < count; j++) {
                    arr[index++] = radixTemp[i][j];
                }
                radixCount[i] = 0;
            }
        }

        System.out.println("第三轮::" + Arrays.toString(arr));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值