不基于比较的排序:基数排序

这篇具有很好参考价值的文章主要介绍了不基于比较的排序:基数排序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本篇只是讨论桶排序的具体实现,想了解更多算法内容可以在我的博客里搜,建议大家看看这篇排序算法总结:排序算法总结_鱼跃鹰飞的博客-CSDN博客

 桶排序的原理:

不基于比较的排序:基数排序,大厂真题,数据结构与算法,高频面试题,算法,java,数据结构

代码:sort1是一个比较二逼的实现方式浪费空间,sort2是一个正式的方法 文章来源地址https://www.toymoban.com/news/detail-642689.html

package sort;


import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class RadixSort {
    public static void radixSort(int[] arr) {
        int maxBit = getMaxBit(arr);
        sort2(arr, 0, arr.length - 1, maxBit);
    }

    /**
     * 具体的基数排序过程
     * @param arr 排序原始数组
     * @param start 要排序范围开始下标
     * @param end 要排序范围结束下标
     * @param maxBit
     */
    public static void sort(int[] arr, int start, int end, int maxBit) {
        final int bucketSize = 10;
        //先copy一份数据,注意这里的第三个参数要+1,因为是左闭右开
        int[] copy = Arrays.copyOfRange(arr, start, end+1);
        //创建一个Queue数组,长度为10作为桶
        Queue<Integer>[] queues = new LinkedList[bucketSize];
        for(int i = 0; i < bucketSize; i++) {
            queues[i] = new LinkedList();
        }
        for(int digit = 0; digit < maxBit; digit ++) {
            for(int i = start; i <= end; i ++) {
                int bucketNum = digit == 0? copy[i]%10 : (copy[i]/(digit*10))%10;
                //如果是个位的话,直接模10,10位的话,除以digit*10。。。digit*100
                queues[bucketNum].offer(copy[i]);
            }
            //每一次把所有的数放完之后,从桶中倒出,先进去先倒出来(队列实现)
            int curIndex = 0;
            for (int i = start; i <= end; i++) {
                //从0到9挨个取出每个桶里的数据,依次放入copy数组中
                //这就是从桶里倒数据的过程
                for (Queue<Integer> queue : queues) {
                    while (!queue.isEmpty()) {
                        copy[curIndex ++]  = queue.poll();
                    }
                }

            }
        }
        //把排完序的数组复制到原来的数组,如果这个方法是有返回值的,也可以直接返回copy
        for(int i = 0; i < copy.length;i++) {
            arr[i] = copy[i];
        }

    }

    /**
     * 基数排序的省空间的解法
     * @param arr 原始数组
     * @param start 开始下标
     * @param end 结束下标
     * @param maxDigit
     */
    public static void sort2(int[] arr, int start, int end, int maxDigit) {
        final int radixCount = 10;
        //创建一个辅助数组用于中间过程的转换,长度为区间长度
        int[] help = new int[end - start + 1];
        //如果最高位是maxDigit,那从0到maxDigit-1依次进行每一轮的入桶和出桶过程
        for(int digit = 0; digit < maxDigit; digit ++) {
            //统计数组,作为桶使用
            int[] countArr = new int[radixCount];
            //每一轮的入桶操作,countArr[i]代表当前位是i的有多少个数
            for(int i = start; i <= end; i++) {
                int digitNum = getDigitNum(arr[i], digit);
                countArr[digitNum] ++;
            }
            //把countArr改造为前缀和
            //这个循环结束了countArr[i]代表当前位小于等于i的有多少个(i这个数最后的下标是countArr[i]-1)
            for(int i = 0; i < countArr.length; i++) {
                countArr[i] = i == 0? countArr[i] : countArr[i] + countArr[i-1];
            }
            //根据前缀和数组计算当前数字要放的位置
            for(int i = help.length - 1; i >= 0; i --) {
                //取当前位的数
                int digitNum = getDigitNum(arr[i], digit);
                //辅助数组中的countArr[i]代表当前位小于等于i的有多少个,那等于i的最后一个数应该放置在countArr[i]-1位置
                //放完之后等于i的最后没有放元素的还有countArr[i]-1个
                help[--countArr[digitNum]] = arr[i];
            }
            //每一轮拷贝回原数组,方便下次循环用
            for(int i = start; i < end;i++) {
                arr[i] = help[i];
            }
        }


    }

    public static int getDigitNum(int num, int digit) {
        if(digit == 0) return num % 10;
        if(num < Math.pow(10, digit)) {
            return 0;
        }
        int digitNum = num;
        while(digit > 0) {
            digitNum = (digitNum / 10);
            digit --;
        }
        return digitNum%10;
    }

    public static int getMaxBit(int[] arr) {
        int maxBit = 0;
        for(int i = 0; i < arr.length; i++) {
            int curBit = 0;
            int val = arr[i];
            while(val != 0) {
                curBit ++;
                val = val/10;
            }
            maxBit = Math.max(maxBit, curBit);
        }
        return maxBit;
    }

    //判断两个数组每个位置的数是否相等
    public static boolean isEqualsArray(int[] arr1, int[] arr2) {
        if((arr1 == null && arr2 == null) || (arr1 == arr2)) return true;
        if(arr1 == null || arr2 == null || arr1.length != arr2.length)  return false;
        for(int i = 0; i < arr1.length; i++) {
            if(arr1[i] != arr2[i]) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        int[] arr = {103, 9, 13, 17, 25, 27};
        int[] arr2 = {103, 9, 13, 17, 25, 27};
        int maxBit = getMaxBit(arr);
        System.out.println(maxBit);
        boolean isEquals = isEqualsArray(arr, arr2);
        System.out.println(isEquals);
        radixSort(arr);
        printArr(arr);
        /*int digitNum = getDigitNum(3020,1);
        System.out.println(digitNum);*/

    }

    public static void printArr(int[] arr) {
        for(int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}

到了这里,关于不基于比较的排序:基数排序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基数排序MSD和LSD实现和比较

    目录 一.前言 二.算法实现思路 三.算法实现 (1)LSD基数排序 (2)MSD排序 四.算法性能分析和比较 基数排序的关键是“多排序 基数排序(Radix Sort)是一种非比较的排序算法 ,它根据元素的各个位上的值将元素进行排序。它可以分为最低有效位优先(LSD)和最高有效位

    2024年02月03日
    浏览(34)
  • 内部排序算法比较-数据结构C语言课设

    名称: 内部排序算法比较 内容: 在教科书中,各种内部排序算法的时间复杂的分析结果只给出了算法执行时间的阶,或大概执行时间。试通过随机数据比较各种算法的比较次数和移动次数,以取得直观感受。 任务: (1)对以下7中常会用的内部排序算法进行比较

    2024年02月12日
    浏览(43)
  • 【数据结构与算法】内排序算法比较(C\C++)

    各种内部排序算法的时间复杂度分析结果只给出了算法执行时间的阶,或大概执行时间,试通过随机的数据比较各算法的比较次数和移动次数,以取得直观感受。 对以下10种常用的内部排序算法进行比较:直接插入排序、折半插入排序、二路插入排序、希尔排序、

    2024年02月12日
    浏览(39)
  • 【数据结构初阶】十、快速排序(比较排序)讲解和实现(三种递归快排版本 + 非递归快排版本 -- C语言实现)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】九、排序的讲解和实现(直接插入 希尔 直接选择 堆 冒泡 -- C语言)

    2024年02月08日
    浏览(35)
  • 【数据结构初阶】九、五种比较排序的讲解和实现(直接插入 \ 希尔 \ 直接选择 \ 堆 \ 冒泡 -- C语言)

    ========================================================================= 相关代码gitee自取 : C语言学习日记: 加油努力 (gitee.com)  ========================================================================= 接上期 : 【数据结构初阶】八、非线性表里的二叉树(二叉树的实现 -- C语言链式结构)-CSDN博客  ====

    2024年02月08日
    浏览(40)
  • 考研算法33天:基数排序 【基数排序】

    我们前一天写了一道桶排序,今天开始看它的进化版:基数排序,为啥会有这个算法呢?因为我们桶排序有一部是需要统计每个数字出现的次数因此需要开一个相对大的数组 但是就像快速排序这道题,它的数值到了10的9次方了,咋映射呢?总不可能再开这么大一个数组吧?会

    2024年02月11日
    浏览(37)
  • 25.选择排序,归并排序,基数排序

    目录 一. 选择排序 (1)简单选择排序 (2)堆排序 二. 归并排序 三. 基数排序 四. 各种排序方法的比较 (1)时间性能 (2)空间性能 (3)排序方法的稳定性能 (4)关于“排序方法的时间复杂度的下限” 一. 选择排序 (1)简单选择排序 基本思想:在待排序的数据中选出最

    2024年02月10日
    浏览(30)
  • 桶排序 — 计数排序和基数排序

    计数排序 int类型数组,其中存的是员工的年龄。比如说16 - 150。对于这样的数据来讲,数据状况是受限的。此时如果将数组从小到大进行排序,该如果实现? 这个实现很简单,实现一个统计数组范围从 0 ~ 150,新数组下标对应着老数组的值,新数组的值对应着老数组相同值的

    2024年02月07日
    浏览(29)
  • 【手撕排序算法】---基数排序

    个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【数据结构初阶(C实现)】 我们直到一般的排序都是通过的 比较和移动 这两种操作来进行排序的。 而今天介绍的基数排序并不是依靠的 比较和移动 来

    2024年02月16日
    浏览(26)
  • 排序算法————基数排序(RadixSort)

    什么是基数排序???基数排序是一种和快排、归并、希尔等等不一样的排序...它不需要比较和移动就可以完成整型的排序。它是时间复杂度是O(K*N),空间复杂度是O(K+M ) 基数排序是一种借助多的思想对单逻辑进行排序的方法。 基数排序根据每个位来分配

    2024年02月13日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包