基数排序(Java实现)

基数排序是一种高级排序算法。

基数排序需要进行d趟分配和收集,一趟分配需要O(n),一趟收集需要O( r ),所以基数排序的时间复杂度为O(d(n + r))(n表示待排序的记录数,d表示待排序数的最大位数,即所有记录中的最大关键字数,r则是每个关键字的取值范围)。

基数排序相当快,甚至比快速排序还快。但是它最大的缺点就是占内存太大,空间复杂度为O(r )。由于在代码中我们会用到11个辅助一维数组(实际上是一个二维数组和一个一维数组),若是对1亿个数进行排序,会占用100000000 * 11 * 4 / 1024 / 1024 / 1024 ≈ 4.1G内存,若是你的内存比这个小,进行基数排序会报内存不足的错误:OutOfMemoryError: Java Heap Space,所以根据你本机内存适当调整排序数量。

代码:

public class RadixSort {
    public static void main(String[] args) {
        int[] arr = new int[9999999];
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int)(Math.random()*arr.length);
        }
        long start = System.currentTimeMillis();
        radixSort(arr);
        long end = System.currentTimeMillis();
        System.out.println("基数排序耗时:" + (end - start) + "ms");
    }

    public static void radixSort(int[] arr){
        int[][] buckets = new int[10][arr.length]; //10个桶,每个桶又是一维数组
        int[] bucketNum = new int[10]; //每个桶当前存储数的数量
        //找出最大位数(即代表循环轮数)
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max)
                max = arr[i];
        }
        int circularNum = (max + "").length(); //循环轮数
        for (int i = 0, n = 1; i < circularNum; i++, n *= 10) {
            for (int value : arr) {
                int bit = value / n % 10; //个位、十位、百位、... bit表示存到第几桶
                buckets[bit][bucketNum[bit]++] = value;
            }
            //桶里的数按顺序存回arr
            int index = 0;
            for (int j = 0; j < buckets.length; j++) {
                for (int k = 0; k < bucketNum[j]; k++) {
                    arr[index++] = buckets[j][k];
                }
                bucketNum[j] = 0; //清空该桶(实际上没有清空,不过后续都会被覆盖)
            }
        }
    }
}

运行结果表示排序相当快,把空间换时间做到了极致,可能接近线性时间复杂度。比我们之前测试过的希尔排序堆排序归并排序快速排序要快得多!
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值