数据结构与算法Java实现-16基数排序

Java数据结构与算法 专栏收录该内容
17 篇文章 0 订阅

基数排序

package aStudy.day6;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * @author haoqi
 * @Date 2020/10/4 - 10:16
 * 基数排序
 * 桶排序的优化,利用空间换时间
 *
 */
public class data07 {
    public static void main(String[] args) {

//        int arr[] = { 53, 3, 542, 748, 14, 214}; //最高百分位,只进行 个 十 百 三轮排序
        int[] arr = new int[80000]; //数据过大会撑爆内存 注意!!! //Java heap space
        for (int i = 0; i < 80000; i++) {
            arr[i] = (int) (Math.random()*80000); // [0,80000);
        }
        System.out.println("第0轮,对个位的排序处理 arr =" + Arrays.toString(arr)); //[53, 3, 542, 748, 14, 214]
//        radisSort01(arr);

        //测试效率
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //1
        Date data1 = new Date();
        String date1Str = simpleDateFormat.format(data1);
        System.out.println("排序前的时间是=" + date1Str);

        radisSort01(arr);

        //0
        Date data2 = new Date();
        String date2Str = simpleDateFormat.format(data2);
        System.out.println("排序前的时间是=" + date2Str);

//        System.out.println("基数排序后 " + Arrays.toString(arr));

//        排序前的时间是=2020-10-04 11:03:05
//        排序前的时间是=2020-10-04 11:03:05

    }

    public static void radisSort(int[] arr){

        //定义二维数组,表示10个桶,每个桶表示一维数组,存放对应位的值
        //1. 二维数组包含10个一维数组
        //2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
        //3. 名明确,基数排序是使用空间换时间的经典算法
        int[][] bucket = new int[10][arr.length]; //arr.length 防止栈溢出

        //为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
        //可以这里理解
        //比如:bucketElementCounts[0] , 记录的就是  bucket[0] 桶的放入数据个数
        int[] bucketNum = new int[10];

        //第1轮,对于每个元素的个位,进行排序处理放相应入桶中
        for (int j = 0; j < arr.length; j++) {
            //取出每个元素个位值
            int digitVal = arr[j]/1%10;
            //放入对应的桶中
            bucket[digitVal][bucketNum[digitVal]] = arr[j];
            bucketNum[digitVal]++;//==
        }
        //桶的顺序(然后一维数组下标依次弹出数据,放入原来的数组)
        int index = 0;
        //遍历每个桶,有数据才放人原来的数组
        for (int k = 0; k < bucketNum.length; k++) {
            if (bucketNum[k] != 0){
                //循环k桶(第k个一维数组)放入
                for (int l = 0; l < bucketNum[k]; l++) {
                    //取出元素,放到arr中
                    arr[index++] = bucket[k][l];
                }
            }
            //处理完数据后,要将每个 bucketNum[k] = 10 !!! 进行归位
            bucketNum[k] = 0;
        }
        System.out.println("第1轮,对个位的排序处理 arr =" + Arrays.toString(arr)); //[542, 53, 3, 14, 214, 748]

        //同理,以后每轮只需要取出相应轮的 分位值 即可
        //第2轮,对于每个元素的个位,进行排序处理放相应入桶中
        for (int j = 0; j < arr.length; j++) {
            //取出每个元素个位值
            int digitVal = arr[j]/10%10; //取出相应轮的 分位值 即可
            //放入对应的桶中
            bucket[digitVal][bucketNum[digitVal]] = arr[j];
            bucketNum[digitVal]++;//==
        }
        //桶的顺序(然后一维数组下标依次弹出数据,放入原来的数组)
        index = 0;
        //遍历每个桶,有数据才放人原来的数组
        for (int k = 0; k < bucketNum.length; k++) {
            if (bucketNum[k] != 0){
                //循环k桶(第k个一维数组)放入
                for (int l = 0; l < bucketNum[k]; l++) {
                    //取出元素,放到arr中
                    arr[index++] = bucket[k][l];
                }
            }
            //处理完数据后,要将每个 bucketNum[k] = 10 !!! 进行归位
            bucketNum[k] = 0;
        }
        System.out.println("第2轮,对个位的排序处理 arr =" + Arrays.toString(arr)); //[3, 14, 214, 542, 748, 53]


        //第2轮,对于每个元素的个位,进行排序处理放相应入桶中
        for (int j = 0; j < arr.length; j++) {
            //取出每个元素个位值
            int digitVal = arr[j]/100%10; //取出相应轮的 分位值 即可
            //放入对应的桶中
            bucket[digitVal][bucketNum[digitVal]] = arr[j];
            bucketNum[digitVal]++;//==
        }
        //桶的顺序(然后一维数组下标依次弹出数据,放入原来的数组)
        index = 0;
        //遍历每个桶,有数据才放人原来的数组
        for (int k = 0; k < bucketNum.length; k++) {
            if (bucketNum[k] != 0){
                //循环k桶(第k个一维数组)放入
                for (int l = 0; l < bucketNum[k]; l++) {
                    //取出元素,放到arr中
                    arr[index++] = bucket[k][l];
                }
            }
            //处理完数据后,要将每个 bucketNum[k] = 10 !!! 进行归位
            bucketNum[k] = 0;
        }
        System.out.println("第2轮,对个位的排序处理 arr =" + Arrays.toString(arr)); //[3, 14, 53, 214, 542, 748]

    }

    //======================================
    //封装
    public static void radisSort01(int[] arr){

        //找到数组中最大数
        int max = arr[0]; //假设第一数就是最大数
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] > max)
                max = arr[i];
        }
        //得到最大数是几位数
        int maxLength = (max + "").length();

        int[][] bucket = new int[10][arr.length]; //arr.length 防止栈溢出
        int[] bucketNum = new int[10]; //记录桶里面的元素

        //每轮排序操作改为循环
        for (int i=0,n=1 ; i < maxLength; i++,n*=10) {
            //第i轮,对于每个元素的个位,进行排序处理放相应入桶中
            for (int j = 0; j < arr.length; j++) {
                //取出每个元素个位值
                int digitVal = arr[j]/n%10;
                //放入对应的桶中
                bucket[digitVal][bucketNum[digitVal]] = arr[j];
                bucketNum[digitVal]++;//==
            }
            //桶的顺序(然后一维数组下标依次弹出数据,放入原来的数组)
            int index = 0;
            //遍历每个桶,有数据才放人原来的数组
            for (int k = 0; k < bucketNum.length; k++) {
                if (bucketNum[k] != 0){
                    //循环k桶(第k个一维数组)放入
                    for (int l = 0; l < bucketNum[k]; l++) {
                        //取出元素,放到arr中
                        arr[index++] = bucket[k][l];
                    }
                }
                //处理完数据后,要将每个 bucketNum[k] = 10 !!! 进行归位
                bucketNum[k] = 0;
            }
//            System.out.println("第i轮,对个位的排序处理 arr =" + Arrays.toString(arr)); //[542, 53, 3, 14, 214, 748]

        }
    }

}

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页

打赏作者

侯浩琪

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值