基数排序

介绍

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

基本思想

首先定义10个“桶”,下标为0~9;然后遍历数组,按照元素的“个位”数值,依次放入对应下标的桶中,放完所有元素后,从第0个桶开始遍历,依次取出桶中元素按顺序放入原始数组中;同理,之后再遍历数组,按照元素的“十位”数值,做上一步相同的操作;以此类推,直到按照数组中最大元素的最高位操作完为止。

思路



代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.nanzx.sort;

import java.util.Arrays;

public class RadixSort {

public static void main(String[] args) {
int arr[] = { 53, 3, 542, 748, 14, 214 };
radixSort(arr);
}

public static void radixSort(int[] arr) {

// 1. 二维数组包含10个一维数组,表示10个桶, 每个桶就是一个一维数组
// 2. 为了防止在放入数的时候,数据溢出,则每个一维数组(桶),大小定为arr.length
// 3. 基数排序是使用空间换时间的经典算法
int[][] bucket = new int[10][arr.length];
// 为了记录每个桶中实际存放了多少个数据,我们定义一个一维数组来记录各个桶的每次放入的数据个数
// 比如:bucketElementCounts[0] , 记录的就是 bucket[0] 桶的放入数据个数
int[] bucketElementCounts = new int[10];

// 第1轮(针对每个元素的个位进行排序处理)
for (int i = 0; i < arr.length; i++) {//按照位数放入对应的桶中
int digitOfElement = arr[i] / 1 % 10;//获得个位数
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[i];
bucketElementCounts[digitOfElement]++;
}
int index = 0;
//遍历每一个桶,并将桶中的数据,放入到原数组中
for (int i = 0; i < bucketElementCounts.length; i++) {
if (bucketElementCounts[i] != 0) {
for (int j = 0; j < bucketElementCounts[i]; j++) {
arr[index++] = bucket[i][j];
}
}
bucketElementCounts[i] = 0;//清零,方便下一轮使用
}
System.out.println("第1轮,对个位的排序处理 arr =" + Arrays.toString(arr));

for (int i = 0; i < arr.length; i++) {
int digitOfElement = arr[i] / 10 % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[i];
bucketElementCounts[digitOfElement]++;
}
index = 0;
for (int i = 0; i < bucketElementCounts.length; i++) {
if (bucketElementCounts[i] != 0) {
for (int j = 0; j < bucketElementCounts[i]; j++) {
arr[index++] = bucket[i][j];
}
}
bucketElementCounts[i] = 0;
}
System.out.println("第2轮,对十位的排序处理 arr =" + Arrays.toString(arr));

for (int i = 0; i < arr.length; i++) {
int digitOfElement = arr[i] / 100 % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[i];
bucketElementCounts[digitOfElement]++;
}
index = 0;
for (int i = 0; i < bucketElementCounts.length; i++) {
if (bucketElementCounts[i] != 0) {
for (int j = 0; j < bucketElementCounts[i]; j++) {
arr[index++] = bucket[i][j];
}
}
bucketElementCounts[i] = 0;
}
System.out.println("第3轮,对百位的排序处理 arr =" + Arrays.toString(arr));
}
}

运行结果

第1轮,对个位的排序处理 arr =[542, 53, 3, 14, 214, 748]
第2轮,对十位的排序处理 arr =[3, 14, 214, 542, 748, 53]
第3轮,对百位的排序处理 arr =[3, 14, 53, 214, 542, 748]

整合代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.nanzx.sort;

import java.util.Arrays;

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));
}

public static void radixSort(int[] arr) {
int[][] bucket = new int[10][arr.length];
int[] bucketElementCounts = new int[10];

//获取最大数有多少位
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
int maxLength = (max + "").length();

for (int k = 0, n = 1; k < maxLength; k++, n *= 10) {
for (int i = 0; i < arr.length; i++) {
int digitOfElement = arr[i] / n % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[i];
bucketElementCounts[digitOfElement]++;
}
int index = 0;
for (int i = 0; i < bucketElementCounts.length; i++) {
if (bucketElementCounts[i] != 0) {
for (int j = 0; j < bucketElementCounts[i]; j++) {
arr[index++] = bucket[i][j];
}
}
bucketElementCounts[i] = 0;
}
}
}
}

测试基数排序的速度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.nanzx.sort;

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

public class RadixSort {

public static void main(String[] args) {;
// 创建要给8000000个的随机的数组,八百万
int[] arr = new int[8000000];
for (int i = 0; i < 8000000; 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);
}

public static void radixSort(int[] arr) {
int[][] bucket = new int[10][arr.length];
int[] bucketElementCounts = new int[10];

//获取最大数有多少位
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
int maxLength = (max + "").length();

for (int k = 0, n = 1; k < maxLength; k++, n *= 10) {
for (int i = 0; i < arr.length; i++) {
int digitOfElement = arr[i] / n % 10;
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[i];
bucketElementCounts[digitOfElement]++;
}
int index = 0;
for (int i = 0; i < bucketElementCounts.length; i++) {
if (bucketElementCounts[i] != 0) {
for (int j = 0; j < bucketElementCounts[i]; j++) {
arr[index++] = bucket[i][j];
}
}
bucketElementCounts[i] = 0;
}
}
}
}

排序前的时间是=2020-08-03 21:35:10 排序后的时间是=2020-08-03 21:35:11