基数排序

要点:按照位数排序,从个位数开始,位数不够则补零,将数字放置在其位数相对应的桶中,然后再从桶中依次取出排序,如此循环直到最高位,循环次数由数组中最大的绝对值的位数决定。

package DataStructure;

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

public class RadixSort {
    public static void main(String[] args) {
//        int[] arr = {55, 48, 0, 24, -88, 120, 558, -1, 1256, 26842};
//        sort3(arr);
//        System.out.println(Arrays.toString(arr));
        int[] arr = new int[8000000];
        for (int i = 0; i < 8000000; i++) {
            arr[i] = (int) (Math.random() * 800000); // 即[0,1) * 800000
        }

        sort(arr); // 8000000个数据,使用ArrayList耗时约5秒
        sort2(arr); // 8000000个数据,使用二维数组耗时约2秒
    }

    // 使用ArrayList代替二维数组
    public static void sort (int[] arr) {
        ArrayList<Integer>[] bucket = new ArrayList[10];
        for (int i = 0; i < 10; i++) {
            bucket[i] = new ArrayList<>(arr.length);
        }
        // 获取最大值的位数
        int maxLength = (getMax(arr) + "").length();

        // 从个位开始循环,将数值放入与位数相对应的桶中
        for (int i = 0; i < maxLength; i++) {
            for (int num : arr) {
                int j = (num / (int)Math.pow(10, i)) % 10;
                bucket[j].add(num);
            }
            for (int k = 0, s = 0; k < 10; k++) {
                for (int l = 0; l < bucket[k].size(); l++) {
                    arr[s++] = bucket[k].get(l);
                }
                // 添加完数据后,务必要清空每一个桶。
                bucket[k].clear();
            }
        }
    }

    // 使用二维数组
    public static void sort2 (int[] arr) {
        // 十个桶,每个桶的长度为数组元素个数。
        int[][] bucket = new int[10][arr.length];
        // 获取最大值的位数
        int maxLength = (getMax(arr) + "").length();

        // 创建一个数组,用于记录每一个桶中添加的元素个数:
        int[] valueNum = new int[10];

        // 从个位开始循环,将数值放入与位数相对应的桶中
        for (int i = 0; i < maxLength; i++) {
            for (int num : arr) {
                int j = (num / (int)Math.pow(10, i)) % 10;
                // j表示第j个桶,valueNum[j]表示第j个桶的元素个数,添加到桶后,valueNum[j]++
                bucket[j][valueNum[j]++] = num;
            }
            // 遍历每个桶,将元素依次添加到原数组中:
            for (int k = 0, s = 0; k < 10; k++) {
                if (valueNum[k] != 0) {
                    for (int l = 0; l < valueNum[k]; l++) {
                        arr[s++] = bucket[k][l];
                    }
                    // 添加完后,务必将桶清零
                    valueNum[k] = 0;
                }
            }
        }
    }

    // 考虑负数
    public static void sort3 (int[] arr) {
        // 二十个桶,0~9负数,10~19正数,每个桶的长度为数组元素个数。
        int[][] bucket = new int[20][arr.length];
        // 获取最大绝对值的位数
        int maxLength = (getAbsMax(arr) + "").length();

        // 创建一个数组,用于记录每一个桶中添加的元素个数:
        int[] valueNum = new int[20];

        // 从个位开始循环,将数值放入与位数相对应的桶中
        for (int i = 0; i < maxLength; i++) {
            for (int num : arr) {
                int j = (num / (int)Math.pow(10, i)) % 10;
                // num为负数时加到0~9桶,num为正数时加到10~19桶。
                if (num < 0) {
                    bucket[j + 9][valueNum[j + 9]++] = num;
                }else {
                    bucket[j + 10][valueNum[j + 10]++] = num;
                }
            }
            // 遍历每个桶,将元素依次添加到原数组中:
            for (int k = 0, s = 0; k < 20; k++) {
                if (valueNum[k] != 0) {
                    for (int l = 0; l < valueNum[k]; l++) {
                        arr[s++] = bucket[k][l];
                    }
                    // 添加完后,务必将桶清零
                    valueNum[k] = 0;
                }
            }
        }
    }

    // 获取数组中的最大值
    public static int getMax(int[] arr) {
        int max = arr[0];
        for (int value : arr) {
            if (value > max) {
                max = value;
            }
        }
        return max;
    }

    // 获取数组中的绝对值最大值
    public static int getAbsMax(int[] arr) {
        int max = Math.abs(arr[0]);
        for (int value : arr) {
            int absValue = Math.abs(value);
            if (absValue > max) {
                max = absValue;
            }
        }
        return max;
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值