小白初识 - 基数排序(RadixSort)

基数排序算是桶排序和计数排序的衍生吧,因为基数排序里面会用到这两种其中一种。

基数排序针对的待排序元素是要有高低位之分的,比如单词adobe,activiti,activiti就高于adobe,这个是根据ascll码来的。

 

现在我们可以提出一个问题,怎样对字典里面的单词进行排序呢?

比如我们现在有如下单词:

"Java", "Mongodb", "Redis", "Kafka", "javascript", "mysql", "mybatis", "kindle", 
"rpc", "Algorithm", "mergeSort", "quickSort", "Adobe"

我们要怎么对它排序呢,这里就可以用到基数排序了,基数排序的原理就是我们将一个元素按高低位分成单个个体,比如Adobe我们

就分成A,d,o,b,e,Algorithm我们就分成A,l,g,o,r,i,t,h,m,然后我们从右往左,依次比较即可。

但是这里Adobe和Algorithm并不能直接比较,因为他们的长短不一,所以在比较之前我们应该找到最长的元素的长度,然后将其余短的元素补全

到一样长:

Adobe0000

Algorithm

这样才可以形成比较,从右往左,0:m,0:h,0:t,0:i,e:r,b:o,o:g,d:l,A:A,我们就可以比较出来Adobe > Algorihtm

跟着以下的图片会更清楚原理:

从上图我们可以看出,基数排序会从右往左依次比较(即在我们的程序实现里面需要遍历很多次),而具体要遍历多少次则取决于最长的元素有多长,从右往左对每个位
的元素比较可以用到桶排序或计数排序,桶排序和计数排序的时间复杂度都是O(n),假设最大的元素长度为K,则基数排序的时间复杂度为O(k * n),而k一般不会有多大,
可以视为常量,所以基数排序的时间复杂度也是O(n)。

以下是我的Java实现:
  1 package com.structure.sort;
  2 
  3 /**
  4  * @author zhangxingrui
  5  * @create 2019-01-30 14:58
  6  **/
  7 public class RadixSort {
  8 
  9     public static void main(String[] args) {
 10         /*int[] numbers = {19, 36, 24, 10, 9, 29, 1, 0, 3, 60, 100, 1001, 999, 520, 123, 96};
 11         radixSort(numbers);
 12         for (int number : numbers) {
 13             System.out.println(number);
 14         }*/
 15 
 16         String[] words = {"Java", "Mongodb", "Redis", "Kafka", "javascript", "mysql", "mybatis", "kindle", "rpc", "Algorithm", "mergeSort", "quickSort", "Adobe"};
 17 //        String[] words = {"Java", "mongodb", "Kafka"};
 18         radixSort(words);
 19         for (String word : words) {
 20             System.out.println(word.replaceAll("0", ""));
 21         }
 22     }
 23 
 24     /**
 25      * @Author: xingrui
 26      * @Description: 基数排序(单词)
 27      * @Date: 15:53 2019/1/30
 28      */
 29     private static void radixSort(String[] words){
 30         int exp = 0;
 31         int maxLength = getMaxLength(words);
 32         autoComplete(words, maxLength);
 33         for(exp = 1; exp <= maxLength; exp++){
 34             countingSort(words, exp);
 35         }
 36     }
 37 
 38     /**
 39      * @Author: xingrui
 40      * @Description: 计数排序(单词)
 41      * @Date: 13:57 2019/1/30
 42      */
 43     private static void countingSort(String[] words, int exp){
 44         int n = words.length;
 45         String[] r = new String[n];
 46         int[] c = new int[122];
 47 
 48         for(int i = 0; i < n; ++i){
 49             int asc = (byte)words[i].charAt(words[i].length() - exp);
 50             c[asc]++;
 51         }
 52 
 53         for(int i = 1; i < 122; ++i){
 54             c[i] = c[i-1] + c[i];
 55         }
 56 
 57         for (int i = n - 1; i >= 0; --i){
 58             int asc = (byte)words[i].charAt(words[i].length() - exp);
 59             int index = c[asc];
 60             r[index - 1] = words[i];
 61             c[asc]--;
 62         }
 63 
 64         for(int i = 0; i < n; ++i){
 65             words[i] = r[i];
 66         }
 67     }
 68 
 69     /**
 70      * @Author: xingrui
 71      * @Description: 基数排序(纯数字)
 72      * @Date: 15:00 2019/1/30
 73      */
 74     private static void radixSort(int[] numbers){
 75         int exp = 0;
 76         int maxNumber = getMaxNumber(numbers);
 77         for(exp = 1; maxNumber/exp > 0; exp *= 10){
 78             countingSort(numbers, exp);
 79         }
 80     }
 81 
 82     /**
 83      * @Author: xingrui
 84      * @Description: 计数排序(纯数字)
 85      * @Date: 13:57 2019/1/30
 86      */
 87     private static void countingSort(int[] numbers, int exp){
 88         int n = numbers.length;
 89 
 90         int[] r = new int[n];
 91         int[] c = new int[10];
 92 
 93         for(int i = 0; i < n; ++i){
 94             c[numbers[i]/exp % 10]++;
 95         }
 96 
 97         for(int i = 1; i < 10; ++i){
 98             c[i] = c[i-1] + c[i];
 99         }
100 
101         for (int i = n - 1; i >= 0; --i){
102             int index = c[numbers[i] / exp % 10];
103             r[index - 1] = numbers[i];
104             c[numbers[i] / exp % 10]--;
105         }
106 
107         for(int i = 0; i < n; ++i){
108             numbers[i] = r[i];
109         }
110     }
111 
112     /**
113      * @Author: xingrui
114      * @Description: 自动补全单词
115      * @Date: 16:38 2019/1/30
116      */
117     private static void autoComplete(String[] words, int maxLength){
118         int i = 0;
119         for (String word : words) {
120             if(word.length() < maxLength){
121                 int value = maxLength - word.length();
122                 StringBuilder sb = new StringBuilder();
123                 for(int j = 0; j < value; ++j){
124                     sb.append("0");
125                 }
126                 words[i] = word + sb;
127             }
128             i++;
129         }
130     }
131 
132     /**
133      * @Author: xingrui
134      * @Description: 获取字符串最大的长度
135      * @Date: 15:56 2019/1/30
136      */
137     private static int getMaxLength(String[] words){
138         int maxLength = words[0].length();
139         for(int i = 1; i < words.length; ++i){
140             if(words[i].length() > maxLength)
141                 maxLength = words[i].length();
142         }
143         return maxLength;
144     }
145 
146     /**
147      * @Author: xingrui
148      * @Description: 获取最大的数字
149      * @Date: 15:56 2019/1/30
150      */
151     private static int getMaxNumber(int[] numbers){
152         int maxNumber = numbers[0];
153         for(int i = 1; i < numbers.length; ++i){
154             if(numbers[i] > maxNumber)
155                 maxNumber = numbers[i];
156         }
157         return maxNumber;
158     }
159 
160 }

其中需要注意就是在排序之前需要找到最大的元素长度以确定循环次数和根据最大元素长度补全比较短的元素。

程序执行结果:

 

需要特别说明的是,文中的图片均截图极客网王争老师的专栏《数据结构与算法之美》,如有侵权,请联系我删除。

有需要的朋友也可以去订阅这个专栏,讲的挺不错的,没有视频,只有文字和音频。

转载于:https://www.cnblogs.com/alinainai/p/10340048.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值