第七章:排序算法

本文介绍了基数排序(Radix Sort)的基本概念、工作原理及其稳定性。这是一种分配式排序,通过数字的每一位进行桶排序,适用于大量数据的稳定排序。文中给出了一个Java实现的例子,详细展示了如何利用桶排序进行多位数字的排序过程,包括个位、十位和百位的排序步骤。但需要注意,基数排序在处理海量数据时可能导致内存问题,且不适合包含负数的数组。
摘要由CSDN通过智能技术生成

7.11基数排序

基数排序(桶排序)介绍:
1、 基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶 子法”(bucket sort)或bin sort,顾名思义,它是通过键值的各个位的值, 将要排序的元素分配至某些“桶”中,达到排序的作用
2、 基数排序法是属于稳定性的排序,基数排序法的是效率高的稳定性排序法
3、 基数排序(Radix Sort)是桶排序的扩展
4、 基数排序是1887年赫尔曼·何乐礼发明的。它是这样实现的:将整数按位数切割成不同的数字,然后按每个位数分别比较

基数排序基本思想:
将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后, 从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后, 数列就变成一个有序序列

基数排序的步骤说明:
1、 第一轮按照个位数字进行排序
在这里插入图片描述
2、 第二轮按照十位数字进行排序
在这里插入图片描述

3、 第三轮按照百位数字进行排序
在这里插入图片描述

4、 以此类推

基数排序的说明:
1、 基数排序是对传统桶排序的扩展,速度很快
2、 基数排序是经典的空间换时间的方式,占用内存很大, 当对海量数据排序时, 容易造成 OutOfMemoryError
3、 基数排序时稳定的。[注:假定在待排序的记录序列中,存在多个具有相同的关键字的记录, 若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的]
4、 有负数的数组,我们不用基数排序来进行排序

package com.atguigu06.sort;

import java.util.Arrays;

/**
 * @author peng
 * @date 2021/11/22 - 19:52
 * <p>
 * 实现桶排序:
 * 1、创建0-9,九个桶(实质上是九个一维数组);
 * 2、将需要排序的数,按照个位的数分配到九个桶之中;
 * 3、再根据桶的顺序将每个桶中数字放回到数组中;
 * 4、再按照十位的数字分配到各个桶中;
 * 5、再根据顺序将桶中的数字放回到数组之中
 * 6、以此类推,直到数组的顺序不再发生变化。
 */
public class RadixSort {
    public static void main(String[] args) {
        int[] array = {53, 3, 542, 748, 14, 214};//需要排序的数组
        System.out.println("排序前的数组为:");
        System.out.println(Arrays.toString(array));
        //调用基数排序算法
        radixSort(array);
        System.out.println("排序后的数组为:");
        System.out.println(Arrays.toString(array));
    }

    /**
     * 实现基数排序算法
     */
    public static void radixSort(int[] array) {
        //首先定义一个二维数组表示10个桶
        int[][] bucket = new int[10][array.length];//基数排序算法是空间换取时间的算法
        int[] bucketCount = new int[10];//用于记录每一个桶中元素的个数
        //先求出整个数组的最大位数是多少位,所以要先找到数组的最大值
        int max = array[0];//假设第一个是最大值
        for (int i = 1; i < array.length; i++) {
            //注意一个小细节,这里遍历数组是从1开始的
            if (array[i] > max) {
                max = array[i];
            }
        }
        //for循环之后就找到了最大值,现在要知道最大值的位数是多少
        //一个最简单的办法就是将数字转换成字符串,然后直接统计字符串的长度就可以了
        int maxlength = (max + "").length();//将数字和空字符串拼接之后变成了字符串,再统计字符串的长度
        for (int k = 0; k < maxlength; k++) {
            //遍历最大的长度,这就是要进行装桶的次数
            for (int i = 0; i < array.length; i++) {
                //遍历数组中的每一个数
                int digitOfElement = array[i] / (10 ^ k) % 10;//获取元素轮数对应的位数数字
                bucket[digitOfElement][bucketCount[digitOfElement]] = array[i];//将对应的数放在对应的桶中,并且计数
                bucketCount[digitOfElement]++;//因为放进了一个数,所以要加一
            }
            //按照桶的顺序将桶中元素放回到数组之中
            //遍历每一个桶,并将桶中的数据放回到数组之中
            int index = 0;//等下将桶中数据放回数组中时,要用到
            for (int i = 0; i < bucket.length; i++) {
                if (bucketCount[i] != 0) {
                    //如果桶中的数据不为0,遍历这个桶,将桶中的数据放回到数组之中
                    for (int j = 0; j < bucketCount[i]; j++) {
                        array[index] = bucket[i][j];//将桶中的数据放回到数组之中
                        index++;
                    }
                    //将桶中记录元素的数字清理掉
                    //在原视频中,老师将【bucketCount[i] = 0;】放在if之外,我认为桶中只有有数据才能进入if里面,就是说有数据的桶才需要清0
                    //在if之外清0,那么那些没有数据的桶也会进行清0操作,显然这是走多了一步
                    bucketCount[i] = 0;
                }
            }
        }
//        //第一轮
//        //遍历最大的长度,这就是要进行装桶的次数
//        for (int i = 0; i < array.length; i++) {
//            //遍历数组中的每一个数
//            int digitOfElement = array[i] / (10 ^ k) % 10;//获取元素的个位数字
//            bucket[digitOfElement][bucketCount[digitOfElement]] = array[i];//将对应的数放在对应的桶中,并且计数
//            bucketCount[digitOfElement]++;//因为放进了一个数,所以要加一
//        }
//        //按照桶的顺序将桶中元素放回到数组之中
//        //遍历每一个桶,并将桶中的数据放回到数组之中
//        int index = 0;//等下将桶中数据放回数组中时,要用到
//        for (int i = 0; i < bucket.length; i++) {
//            if (bucketCount[i] != 0) {
//                //如果桶中的数据不为0,遍历这个桶,将桶中的数据放回到数组之中
//                for (int j = 0; j < bucketCount[i]; j++) {
//                    array[index] = bucket[i][j];//将桶中的数据放回到数组之中
//                    index++;
//                }
//                //将桶中记录元素的数字清理掉
//                //在原视频中,老师将【bucketCount[i] = 0;】放在if之外,我认为桶中只有有数据才能进入if里面,就是说有数据的桶才需要清0
//                //在if之外清0,那么那些没有数据的桶也会进行清0操作,显然这是走多了一步
//                bucketCount[i] = 0;
//            }
//        }
//
//        //进行第二轮的排序
//        //第一步:将数组中的元素按照十位数的顺序放进桶中
//        for (int i = 0; i < array.length; i++) {
//            int digitOfElement = array[i] / 10 % 10;//获取元素的十位上的数字
//            //将元素按照数字放在对应的桶中
//            bucket[digitOfElement][bucketCount[digitOfElement]] = array[i];//将数字放在对应的桶中
//            bucketCount[digitOfElement]++;//桶中的数量加一
//        }
//        //第二步:将桶中的数字按照桶的顺序取出,放回到数组中去
//        index = 0;//数组的索引要重新置为0
//        for (int i = 0; i < bucket.length; i++) {
//            if (bucketCount[i] != 0) {
//                //如果该桶中的数量不为0,说明该桶中是有元素的,如果为0 ,则说明没有元素就可以直接跳过这个桶了
//                for (int j = 0; j < bucketCount[i]; j++) {
//                    //遍历有数据的桶, 将桶中的数据放回到数组中去
//                    array[index] = bucket[i][j];
//                    index++;
//                }
//                //每遍历完一个桶,要将桶中数据置为0
//                bucketCount[i] = 0;
//            }
//        }
//
//        //进行第三轮的排序
//        //第一步:将数组中的元素按照十位数的顺序放进桶中
//        for (int i = 0; i < array.length; i++) {
//            int digitOfElement = array[i] / 100 % 10;//获取元素的十位上的数字
//            //将元素按照数字放在对应的桶中
//            bucket[digitOfElement][bucketCount[digitOfElement]] = array[i];//将数字放在对应的桶中
//            bucketCount[digitOfElement]++;//桶中的数量加一
//        }
//        //第二步:将桶中的数字按照桶的顺序取出,放回到数组中去
//        index = 0;//数组的索引要重新置为0
//        for (int i = 0; i < bucket.length; i++) {
//            if (bucketCount[i] != 0) {
//                //如果该桶中的数量不为0,说明该桶中是有元素的,如果为0 ,则说明没有元素就可以直接跳过这个桶了
//                for (int j = 0; j < bucketCount[i]; j++) {
//                    //遍历有数据的桶, 将桶中的数据放回到数组中去
//                    array[index] = bucket[i][j];
//                    index++;
//                }
//                //每遍历完一个桶,要将桶中数据置为0
//                bucketCount[i] = 0;
//            }
//        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值