桶排序

一---导读

  我们先思考这样一个数学问题,如何取出一个数的个位,十位,百位。。。?

以128为例,要取出个位8我们可以对其进行直接取余10操作 128 % 10 = 8,取出十位2我们可以先对其除以10再取余10。

128 % 10 = 12,12 % 10 = 2;

二---桶排算法思路图解

假设现在有数组arr{3, 15, 122, 64}

我们对其用桶排进行排序步骤如下:

第一轮:对个位进行排序

第二轮:对十位进行排序

第三轮:对百位进行排序

 

通过以上的图片我们可以看出,只要排三次,也就是到最高位百位,即可得出想要的结果。

 注:基数排序其实就是桶排序的精简版本

代码实现:

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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package Sort;
 
import java.util.Arrays;
 
public class RadixSort {
    public static void main(String[] args) {
        int[] arr = {3, 15, 12264};
        System.out.println("排序前" + Arrays.toString(arr));
 
        radixSort(arr);
 
    }
 
    // 基数排序
   public static void radixSort(int[] arr) {
 
 
        // 定义一个二维数组,表示10个桶,每个桶就是一个一维数组
        // 说明
        // 1 二维数组包含10个一维数组
        // 2 为了防止数据溢出,则每个一维数组(桶)的大小为arr.length
        // 3 很明显基数排序是使用空间换时间的经典算法
        int[][] bucket = new int[10][arr.length];
        //为了记录每个桶中实际存放了多少个数据,我们定义一个一维数组来记录各个桶每次放入的数据的个数
        // 可以这样理解
        // bucketElementCount[0],记录的就是bucket[0]桶的放入数据个数,可以看做10个指针(没学过c/c++忽略)
        // 可以这样理解,bucketElementCounts[0],记录的是bucket[0]桶的放入数据个数。
        int[] bucketElementCounts = new int[10];
 
        // 第一轮(针对个位进行排序处理)
        for (int j = 0; j < arr.length ; j++) {
            // 取出每个元素的个位
            int digitOfElment = arr[j] / 1 % 10;
            // 放入到对应的桶中,就是刚刚算出来的这个桶
            bucket[digitOfElment][bucketElementCounts[digitOfElment]] = arr[j];
            bucketElementCounts[digitOfElment]++;
        }
        // 按照这个桶的顺序 (一维数组的下标依次取出数据,放入原来数组)
 
        int index = 0;
        // 遍历每一个桶,并将桶中的数据放到原数组
        for (int k = 0; k < bucketElementCounts.length ;  k++) {
            // 如果桶中有数据,我们才放入到原数组。
            if(bucketElementCounts[k] != 0) {
                // 循环该桶即第k个桶,即第k个一维数组,放入
                for (int l = 0; l < bucketElementCounts[k] ;  l++) {
                    // 取出元素放到arr
                    arr[index++] = bucket[k][l];
 
                }
            }
            // 第一轮处理后需要将 每个bucketElementCounts[k]=0
            bucketElementCounts[k] = 0;
        }
 
        System.out.println("第一轮,对个位的数据的处理" + Arrays.toString(arr));
 
 
        // 第二轮(针对十位进行排序处理)
        for (int j = 0; j < arr.length ; j++) {
            // 取出每个元素的个位
            int digitOfElment = arr[j] / 10 % 10;
            // 放入到对应的桶中,就是刚刚算出来的这个桶
            bucket[digitOfElment][bucketElementCounts[digitOfElment]] = arr[j];
            bucketElementCounts[digitOfElment]++;
        }
        // 按照这个桶的顺序 (一维数组的下标依次取出数据,放入原来数组)
 
         index = 0;
        // 遍历每一个桶,并将桶中的数据放到原数组
        for (int k = 0; k < bucketElementCounts.length ;  k++) {
            // 如果桶中有数据,我们才放入到原数组。
            // 注意,上一轮结束后我们并没有把桶里的数清零。第二轮再放的话需要重新进行累积,所以会报错Index 6 out of bounds for length 6
            if(bucketElementCounts[k] != 0) {
                // 循环该桶即第k个桶,即第k个一维数组,放入
                for (int l = 0; l < bucketElementCounts[k] ;  l++) {
                    // 取出元素放到arr
                    arr[index++] = bucket[k][l];
 
                }
            }
            bucketElementCounts[k] = 0;
        }
 
        System.out.println("第二轮,对个位的数据的处理" + Arrays.toString(arr));
 
        // 第三轮(针对十位进行排序处理)
        for (int j = 0; j < arr.length; j++) {
            // 取出每个元素的个位
            int digitOfElment = arr[j] / 100 % 10;
            // 放入到对应的桶中,就是刚刚算出来的这个桶
            bucket[digitOfElment][bucketElementCounts[digitOfElment]] = arr[j];
            bucketElementCounts[digitOfElment]++;
        }
        // 按照这个桶的顺序 (一维数组的下标依次取出数据,放入原来数组)
 
        index = 0;
        // 遍历每一个桶,并将桶中的数据放到原数组
        for (int k = 0; k < bucketElementCounts.length; k++) {
            // 如果桶中有数据,我们才放入到原数组。
            // 注意,上一轮结束后我们并没有把桶里的数清零。第二轮再放的话需要重新进行累积,所以会报错Index 6 out of bounds for length 6
            if (bucketElementCounts[k] != 0) {
                // 循环该桶即第k个桶,即第k个一维数组,放入
                for (int l = 0; l < bucketElementCounts[k]; l++) {
                    // 取出元素放到arr
                    arr[index++] = bucket[k][l];
 
                }
            }
        }
 
        System.out.println("第三轮,对个位的数据的处理" + Arrays.toString(arr));
 
 
    }
 
     
}

  

优化代码:我们发现上面一-三步可以用for循环来包含。

复制代码
 1 package Sort;
 2 
 3 import java.util.Arrays;
 4 
 5 public class RadixSortTest {
 6     public static void main(String[] args) {
 7         int[] arr = {13, 2, 164, 259};
 8         System.out.println("原数组为:" + Arrays.toString(arr));
 9         RadixSort1(arr);
10     }
11 
12     public static void RadixSort1(int[] arr) {
13         // 构造出桶
14         int[][] bucket =  new int[10][arr.length];
15         // 用一个数组来存放每个桶中有多少元素 ,有10个桶就是10个。
16         int[] bucketElementCounts = new int[10];
17 
18         // 第一轮排序
19         // 取出数据的个位23 
24         // 获取最大的数的长度
25         int max = arr[0]; // 假设第一个数就是最大的
26         for(int m = 1; m < arr.length; m++) {
27             if(max < arr[m]) {
28                 max =  arr[m];
29             }
30         }
31         System.out.println("最大的数为:" + max);
32         // 获取最大数的长度
33         int maxlength = (max + "").length(); // 加空串使其变为字符串,注意空串之间不要打空格,否则长度会加1,可以调用length函数
34 
35 
36 
37         for(int l = 0, n = 1; l < maxlength; l++, n *= 10) {
38             for (int i = 0; i < arr.length; i++) {  // 注意这里不是arr.length - 1,要不然最后一位处理不到
39                 int digit = arr[i] / n % 10;
40                 // 放入对应的桶中
41                 bucket[digit][bucketElementCounts[digit]] = arr[i];
42                 // 记录桶数据的数组对应位置加1
43                 bucketElementCounts[digit]++;
44             }
45             // 按照当前顺序取出桶中的元素放回数组中
46             int index = 0;
47             for (int j = 0; j < bucket.length; j++) {
48                 // 先判断这个桶中是否有元素,有元素的话再循环取出
49                 if (bucketElementCounts[j] != 0) {
50                     for (int k = 0; k < bucketElementCounts[j]; k++) {
51                         arr[index++] = bucket[j][k];
52                     }
53                 }
54                 bucketElementCounts[j] = 0;
55 
56             }
57             count++;
58             System.out.println("第" + count + "轮排序完" + Arrays.toString(arr));
59         }
}
复制代码

 

posted on   Love&Share  阅读(46)  评论(0编辑  收藏  举报

编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示