将数组 {53, 3, 542, 748, 14, 214 } 使用基数排序, 进行升序排序
1、代码
package com.rf.springboot01.dataStructure.sort;
import java.util.Arrays;
/**
* @description: 基数排序算法的推导过程示例演示
* @author: xiaozhi
* @create: 2020-08-12 22:23
*/
public class RadixSort {
public static void main(String[] args) {
int arr[] = { 53, 3, 542, 748, 14, 214};
radixSort(arr);
}
/**
* @Description: 基数排序算法的推导过程示例方法
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:25
*/
public static void radixSort(int[] arr){
//定义一个二维数组,表示10个桶, 每个桶就是一个一维数组
//说明
//1. 二维数组包含10个一维数组
//2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
//3. 很明确的表示,基数排序是使用空间换时间的经典算法
int[][] bucket=new int[10][arr.length];
//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
//可以这么理解 比如:bucketElementCounts[0] , 记录的就是 bucket[0] 桶的放入数据个数
int[] bucketElementCounts=new int[10];
/**
* @Description: 第一轮(针对每个元素的个位数进行排序处理)
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:29
*/
for(int j=0;j<arr.length;j++){
//取出每个元素的个位的值
int digitElement=arr[j]/1%10;
//放入到对应的桶中
//1、bucket[digitElement] 表示个位数对应的第个位数的桶
//2、bucketElementCounts[digitElement] 表示个位数对应的第个位数的桶的数据个数
bucket[digitElement][bucketElementCounts[digitElement]]=arr[j];
bucketElementCounts[digitElement]++;
}
//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
//遍历每一桶,并将桶中是数据,放入到原数组
int index=0;
for(int k = 0 ; k < bucket.length ; k++){
//如果桶中有数据,我们才放入到原数组
if( bucketElementCounts[k] !=0){
//循环该桶即第k个桶(即第k个一维数组), 放入
for(int m=0;m<bucketElementCounts[k];m++){
//取出元素放入到arr
arr[index]=bucket[k][m];
index++;
}
}
//第一轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
bucketElementCounts[k] = 0;
}
System.out.println("第1轮,对个位的排序处理 arr =" + Arrays.toString(arr));
/**
* @Description: 第二轮(针对每个元素的十位数进行排序处理)
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:29
*/
for(int j=0;j<arr.length;j++){
//取出每个元素的个位的值
int digitElement=arr[j]/10%10;
//放入到对应的桶中
//1、bucket[digitElement] 表示个位数对应的第个位数的桶
//2、bucketElementCounts[digitElement] 表示个位数对应的第个位数的桶的数据个数
bucket[digitElement][bucketElementCounts[digitElement]]=arr[j];
bucketElementCounts[digitElement]++;
}
//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
//遍历每一桶,并将桶中是数据,放入到原数组
index=0;
for(int k = 0 ; k < bucket.length ; k++){
//如果桶中有数据,我们才放入到原数组
if( bucketElementCounts[k] !=0){
//循环该桶即第k个桶(即第k个一维数组), 放入
for(int m=0;m<bucketElementCounts[k];m++){
//取出元素放入到arr
arr[index]=bucket[k][m];
index++;
}
}
//第二轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
bucketElementCounts[k] = 0;
}
System.out.println("第2轮,对十位的排序处理 arr =" + Arrays.toString(arr));
/**
* @Description: 第三轮(针对每个元素的百位数进行排序处理)
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:29
*/
for(int j=0;j<arr.length;j++){
//取出每个元素的个位的值
int digitElement=arr[j]/100%10;
//放入到对应的桶中
//1、bucket[digitElement] 表示个位数对应的第个位数的桶
//2、bucketElementCounts[digitElement] 表示个位数对应的第个位数的桶的数据个数
bucket[digitElement][bucketElementCounts[digitElement]]=arr[j];
bucketElementCounts[digitElement]++;
}
//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
//遍历每一桶,并将桶中是数据,放入到原数组
index=0;
for(int k = 0 ; k < bucket.length ; k++){
//如果桶中有数据,我们才放入到原数组
if( bucketElementCounts[k] !=0){
//循环该桶即第k个桶(即第k个一维数组), 放入
for(int m=0;m<bucketElementCounts[k];m++){
//取出元素放入到arr
arr[index]=bucket[k][m];
index++;
}
}
//第三轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
bucketElementCounts[k] = 0;
}
System.out.println("第3轮,对百位的排序处理 arr =" + Arrays.toString(arr));
}
}
1、代码
package com.rf.springboot01.dataStructure.sort;
import java.util.Arrays;
/**
* @description: 基数排序算法的完整示例演示
* @author: xiaozhi
* @create: 2020-08-12 22:49
*/
public class RadixSort2 {
public static void main(String[] args) {
int arr[] = { 53, 3, 542, 748, 14, 214};
radixSort(arr);
}
/**
* @Description: 基数排序算法的推导过程示例方法
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:25
*/
public static void radixSort(int[] arr) {
//定义一个二维数组,表示10个桶, 每个桶就是一个一维数组
//说明
//1. 二维数组包含10个一维数组
//2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
//3. 很明确的表示,基数排序是使用空间换时间的经典算法
int[][] bucket = new int[10][arr.length];
//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
//可以这么理解 比如:bucketElementCounts[0] , 记录的就是 bucket[0] 桶的放入数据个数
int[] bucketElementCounts = new int[10];
//1. 得到数组中最大的数的位数
int max = arr[0]; //假设第一数就是最大数
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
//得到最大数是几位数
int maxLength = (max + "").length();
/**
* @Description: 针对每个元素的个位数进行排序处理
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:29
*/
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
//(针对每个元素的对应位数进行排序处理), 第一次是个位,第二次是十位,第三次是百位..
for (int j = 0; j < arr.length; j++) {
//取出每个元素的个位的值
int digitElement = arr[j] / n % 10;
//放入到对应的桶中
//1、bucket[digitElement] 表示个位数对应的第个位数的桶
//2、bucketElementCounts[digitElement] 表示个位数对应的第个位数的桶的数据个数
bucket[digitElement][bucketElementCounts[digitElement]] = arr[j];
bucketElementCounts[digitElement]++;
}
//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
//遍历每一桶,并将桶中是数据,放入到原数组
int index = 0;
for (int k = 0; k < bucket.length; k++) {
//如果桶中有数据,我们才放入到原数组
if (bucketElementCounts[k] != 0) {
//循环该桶即第k个桶(即第k个一维数组), 放入
for (int m = 0; m < bucketElementCounts[k]; m++) {
//取出元素放入到arr
arr[index] = bucket[k][m];
index++;
}
}
//第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
bucketElementCounts[k] = 0;
}
System.out.println("第" + (i + 1) + "轮,对数据位数的排序处理 arr =" + Arrays.toString(arr));
}
}
}
2、运行main函数,运行结果如下:
1、代码
package com.rf.springboot01.dataStructure.sort;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
/**
* @description: 测试基数排序算法所消耗的时间示例
* @author: xiaozhi
* @create: 2020-08-12 22:57
*/
public class RadixSort3 {
public static void main(String[] args) {
int arr[] = new int[10000000];
for(int i=0;i<10000000;i++){//创建一个带有一千万个随机数的数组
arr[i]= (int) (Math.random()*8000000); //随机生成(0到8000000之间)的数
}
Date data1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = simpleDateFormat.format(data1);
System.out.println("排序前的时间是=" + date1Str);
radixSort(arr);
Date data2 = new Date();
String date2Str = simpleDateFormat.format(data2);
System.out.println("排序后的时间是=" + date2Str);
}
/**
* @Description: 基数排序算法的推导过程示例方法
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:25
*/
public static void radixSort(int[] arr) {
//定义一个二维数组,表示10个桶, 每个桶就是一个一维数组
//说明
//1. 二维数组包含10个一维数组
//2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
//3. 很明确的表示,基数排序是使用空间换时间的经典算法
int[][] bucket = new int[10][arr.length];
//为了记录每个桶中,实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
//可以这么理解 比如:bucketElementCounts[0] , 记录的就是 bucket[0] 桶的放入数据个数
int[] bucketElementCounts = new int[10];
//1. 得到数组中最大的数的位数
int max = arr[0]; //假设第一数就是最大数
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
//得到最大数是几位数
int maxLength = (max + "").length();
/**
* @Description: 针对每个元素的个位数进行排序处理
* @Param: [arr]
* @Author: xz
* @return: void
* @Date: 2020/8/12 22:29
*/
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
//(针对每个元素的对数应位进行排序处理), 第一次是个位,第二次是十位,第三次是百位..
for (int j = 0; j < arr.length; j++) {
//取出每个元素的个位的值
int digitElement = arr[j] / n % 10;
//放入到对应的桶中
//1、bucket[digitElement] 表示个位数对应的第个位数的桶
//2、bucketElementCounts[digitElement] 表示个位数对应的第个位数的桶的数据个数
bucket[digitElement][bucketElementCounts[digitElement]] = arr[j];
bucketElementCounts[digitElement]++;
}
//按照这个桶的顺序(一维数组的下标依次取出数据,放入原来数组)
//遍历每一桶,并将桶中是数据,放入到原数组
int index = 0;
for (int k = 0; k < bucket.length; k++) {
//如果桶中有数据,我们才放入到原数组
if (bucketElementCounts[k] != 0) {
//循环该桶即第k个桶(即第k个一维数组), 放入
for (int m = 0; m < bucketElementCounts[k]; m++) {
//取出元素放入到arr
arr[index] = bucket[k][m];
index++;
}
}
//第i+1轮处理后,需要将每个 bucketElementCounts[k] = 0 !!!!
bucketElementCounts[k] = 0;
}
}
}
}
本地计算机,win10系统,8G内存测试带有一千万个随机数的数组,用基数排序耗时大约1秒