数据结构——基数排序(经典以空间换时间案例)

基数排序(经典以空间换取时间案例)

一:基数排序介绍:

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

二:基数排序基本思想:

  • 将所有等待比较的数值统一为同样的位数长度,位数较短的数前面补零。然后,从最低为开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成之后,数列就变成了一个有序序列。
    图文展示:假设有数组[53,3,542,748,14,214]
    步骤1
    步骤2
    步骤3

三:代码

实现思路:

1、首先确定会有几轮入桶和出桶的趟数,趟数是看待排序的数据最大有几位,例如最大数十个三位数,那么总共就会有三轮。
2、一共是个桶,每个桶的大小应该是数组是的长度,最极端的假设是数组中的所有数据都是一样的,那么在进行桶排序的时候,就只会进入一个桶,从而造成有很多空间浪费掉,但现实情况并不会发生,所以基数排序是空间换取时间的经典算法。另外还要有一个数组,数组长度是桶的数量,即数组下标用来表示哪个桶,下标对应的数据表示该桶中有几个数据。
3、接下来就是将数据按照个位,十位,百位。。。的数据的大小分别放入对应的桶中。在放完之后,再从桶中取出数据。注意一点是:每次取出数据之后,都要将记录桶中有多少数据的那个数组中对应的数据置为0。

 package 排序算法;

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

/*
    基数排序
 */
public class RadixSort {
    public static void main(String[] args) {
   //     int[] array = {53,3,542,748,14,214};
        int[] array = new int[80000];
        for (int i = 0; i < array.length; i++) {
            array[i] = (int)(Math.random()*80000);
        }

        Date date = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(date);
        System.out.println(format);

        radixSort(array);

        Date date1 = new Date();
        String format1 = simpleDateFormat.format(date1);
        System.out.println(format1);

    }

    //算法
    public static void radixSort(int[] array){

        //先获得进行操作的次数,次数跟数据的位数相关,其中的数据是三位数,那么总操作次数就是3次
        int max = array[0];
        for (int i = 0; i < array.length; i++) {
            if (array[i]>max){
                max = array[i];
            }
        }
        //获取次数
        int maxLength = (max+"").length();

        //总共十个桶,每个桶的大小应该是数组长度的大小
        int[][] bucket = new int[10][array.length];

        //在定义一个桶,下标表示是第几个桶,对应数据就是桶中存放多少数据
        int[] bucketElementCounts = new int[10];


        for (int i = 0 , n = 1; i < maxLength; i++ , n*=10) {

            //将数据全部存放到桶中。
            for (int j = 0; j < array.length; j++) {
                //获取数据
                int digitOfElement = array[j] / n % 10;
                //将数据存放到数组中
                bucket[digitOfElement][bucketElementCounts[digitOfElement]] = array[j];
                bucketElementCounts[digitOfElement] ++;
            }

            //将数据从桶中取出
            int index = 0;

            for (int k = 0; k < bucketElementCounts.length; k++) {
                if (bucketElementCounts[k]!=0){
                   for (int d = 0;d < bucketElementCounts[k];d++){
                       array[index] = bucket[k][d];
                       index ++;
                   }
                    bucketElementCounts[k] = 0;
                }
            }
        }
        System.out.println(Arrays.toString(array));

    }

}

四:对基数排序的说明

  1. 基数排序是对传统桶排序的扩展,速度很快。
  2. 基数排序是经典的以空间换取时间的方式。占用内存会很大,当面对海量数据进行排序的时候,容易造成OutOfMemeryError。
  3. 基数排序是稳定的,所谓稳定的就是在待排序的记录中,存在多个具有相同关键字的记录,若经过排序,这些记录的相对次序是不变的。即在原序列中r[i] = r[j],且r[i]在r[j]之前,而在排序之后,r[i]仍在r[j]之前,这种排序算法就是稳定的。
  4. 基数排序并不能用来进行有负数的排序。当然也可以支持有负数的排序。
发布了24 篇原创文章 · 获赞 5 · 访问量 2063

猜你喜欢

转载自blog.csdn.net/weixin_43288447/article/details/104200818