Java programming: sorting algorithm-radix sorting

Cardinal sort (bucket sort) introduction:

  1. Radix sort (radix sort) belongs to "distribution sort", also known as "bucket sort" or bin sort. As the name suggests, it assigns the elements to be sorted by the value of each bit of the key value To some "buckets", to achieve the role of sorting
  2. The radix sort method is a stable sort, and the radix sort method is a highly efficient stable sort method
  3. Radix Sort (Radix Sort) is an extension of bucket sort
  4. Cardinal sorting was invented by Hermann Holleri in 1887. It is implemented like this: the integer is cut into different numbers according to the digits, and then compared according to each digit.

Basic idea of ​​radix sorting

  1. Unify all the values ​​to be compared to the same digit length, and padded zeros in front of the shorter digits. Then, starting from the lowest bit, sort one time in sequence. So after sorting from the lowest order to the highest order, the sequence becomes an ordered sequence.
  2. This description is more difficult to understand. Let’s look at a graphic explanation to understand the steps of cardinal sorting.

Cardinal sorting graphic description

Sort the array {53, 3, 542, 748, 14, 214} in ascending order using radix sort.
Insert picture description here

Cardinality sort code implementation

  1. Requirement: sort the array {53, 3, 542, 748, 14, 214} using radix sort, and sort in ascending order
  2. Thinking analysis: the previous picture and text have been made clear

Code

package sort;

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

public class RadixSort {
    
    
    public static void main(String[] args) {
    
    
//        int[] arr = {53, 3, 542, 748, 14, 214};
//        radixSort(arr);
//        System.out.println(Arrays.toString(arr));
        int[] arr = new int[80000];
        for (int i = 0; i < 80000; i++) {
    
    
            arr[i] = (int) (Math.random() * 80000);// 生成一个0-80000的数据
        }
        Date date1 = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str = simpleDateFormat.format(date1);
        System.out.println("排序前的时间为:" + date1Str);
        radixSort(arr);
        Date date2 = new Date();
        String date2Str = simpleDateFormat.format(date2);
        System.out.println("排序后的时间为:" + date2Str);
    }

    public static void radixSort(int[] arr) {
    
    
        // 根据前面的推导过程,可以得到最基数排序代码

        // 1. 需要得到数组中最大的数
        int max = arr[0]; // 假设第一个数就是最大数
        for (int i = 0; i < arr.length; i++) {
    
    
            if (arr[i] > max) {
    
    
                max = arr[i];
            }
        }
        // 2.需要得到数组中最大的数的位数
        int maxLength = (max + "").length();
        // 前面代码仍然不动
        int[][] bucket = new int[10][arr.length];
        int[] bucketElementCounts = new int[10];
        for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
    
    
            // 针对每个元素对应的位数进行处理 第一次个位 第二次十位···
            for (int j = 0; j < arr.length; j++) {
    
    
                int digitOfElement = arr[j] / n % 10;
                bucket[digitOfElement][bucketElementCounts[digitOfElement]++] = arr[j];
            }
            int index = 0;
            for (int k = 0; k < bucketElementCounts.length; k++) {
    
    
                if (bucketElementCounts[k] != 0) {
    
    
                    for (int l = 0; l < bucketElementCounts[k]; l++) {
    
    
                        arr[index++] = bucket[k][l];
                    }
                    bucketElementCounts[k] = 0;
                }
            }
        }
    }

    // 基数排序
    public static void radixSort1(int[] arr) {
    
    

        // 定义一个二维数组,表示十个桶,每个桶就是一个一维数组
        // 说明
        // 1. 二维数组包含10个一维数组
        // 2. 为了防止在放入数字的时候,产生数据溢出错误,则每个一维数组(桶)的大小为arr.length
        // 3. 很明显,基数排序是使用空间换时间的经典算法
        int[][] bucket = new int[10][arr.length];
        // 为了记录每个桶中实际存放了多少个数据,我们定义一个一维数组,记录各个桶的每次放入的数据个数
        // 可以这么理解
        // bucketElementCounts[0] 记录的就是bucket[0]桶的放入数据的个数
        int[] bucketElementCounts = new int[10];

        // 第一轮排序(针对每个元素的个位进行排序处理)
        for (int i = 0; i < arr.length; i++) {
    
    
            // 取出每个元素的个数
            int digitOfElement = arr[i] / 1 % 10;
            // 放入到对应桶中,并将记录桶中个数的数组进行++操作
            bucket[digitOfElement][bucketElementCounts[digitOfElement]++] = arr[i];
        }
        // 按照这个桶的顺组(一维数组的下标依次取出数据,放入原来数组)
        int index = 0;
        // 1. 遍历每一个桶。并将桶中的数据,放入到原数组
        for (int i = 0; i < bucketElementCounts.length; i++) {
    
    
            // 如果桶中有数据,我们才放入到原数组
            if (bucketElementCounts[i] != 0) {
    
    
                // 循环该桶即第k个桶(即第k个一维数组),放入原数组
                for (int j = 0; j < bucketElementCounts[i]; j++) {
    
    
                    // 去除元素,放入到arr
                    arr[index++] = bucket[i][j];
                }
                bucketElementCounts[i] = 0;
            }
        }

        System.out.println("第一轮对个位的排序处理arr=" + Arrays.toString(arr));

        // 第二轮排序(针对每个元素的十位进行排序处理)
        for (int i = 0; i < arr.length; i++) {
    
    
            // 取出每个元素的个数
            int digitOfElement = arr[i] / 10 % 10;
            // 放入到对应桶中,并将记录桶中个数的数组进行++操作
            bucket[digitOfElement][bucketElementCounts[digitOfElement]++] = arr[i];
        }
        // 按照这个桶的顺组(一维数组的下标依次取出数据,放入原来数组)
        index = 0;
        // 1. 遍历每一个桶。并将桶中的数据,放入到原数组
        for (int i = 0; i < bucketElementCounts.length; i++) {
    
    
            // 如果桶中有数据,我们才放入到原数组
            if (bucketElementCounts[i] != 0) {
    
    
                // 循环该桶即第k个桶(即第k个一维数组),放入原数组
                for (int j = 0; j < bucketElementCounts[i]; j++) {
    
    
                    // 去除元素,放入到arr
                    arr[index++] = bucket[i][j];
                }
                // 第一轮处理后,需要将每个bucketElementCounts[k] 置0
                bucketElementCounts[i] = 0;
            }
        }

        System.out.println("第二轮对个位的排序处理arr=" + Arrays.toString(arr));

        // 第三轮排序(针对每个元素的百位进行排序处理)
        for (int i = 0; i < arr.length; i++) {
    
    
            // 取出每个元素的个数
            int digitOfElement = arr[i] / 100 % 10;
            // 放入到对应桶中,并将记录桶中个数的数组进行++操作
            bucket[digitOfElement][bucketElementCounts[digitOfElement]++] = arr[i];
        }
        // 按照这个桶的顺组(一维数组的下标依次取出数据,放入原来数组)
        index = 0;
        // 1. 遍历每一个桶。并将桶中的数据,放入到原数组
        for (int i = 0; i < bucketElementCounts.length; i++) {
    
    
            // 如果桶中有数据,我们才放入到原数组
            if (bucketElementCounts[i] != 0) {
    
    
                // 循环该桶即第k个桶(即第k个一维数组),放入原数组
                for (int j = 0; j < bucketElementCounts[i]; j++) {
    
    
                    // 去除元素,放入到arr
                    arr[index++] = bucket[i][j];
                }
                // 第一轮处理后,需要将每个bucketElementCounts[k] 置0
                bucketElementCounts[i] = 0;
            }
        }

        System.out.println("第三轮对个位的排序处理arr=" + Arrays.toString(arr));
    }
}

Description of radix sort

  1. Cardinality sorting is an extension of traditional bucket sorting, which is very fast.
  2. Cardinality sorting is a classic space-for-time method, which takes up a lot of memory. When sorting massive data, it is easy to cause OutOfMemoryError.
  3. The radix sort is stable. [Note: Assume that there are multiple records with the same key in the sequence of records to be sorted. If sorted, the relative order of these records remains unchanged, that is, in the original sequence, r[i]=r[j] , And r[i] is before r[j], and in the sorted sequence, r[i] is still before r[j], this sorting algorithm is said to be stable; otherwise it is called unstable]
  4. For arrays with negative numbers, we do not use radix sorting to sort them. If you want to support negative numbers, please refer to: https://code.i-harness.com/zh-CN/q/e98fa9

Guess you like

Origin blog.csdn.net/KaiSarH/article/details/108869577