5.3基数排序
基数排序的用途在于对相同位数的编号进行排序,例如学号,商品编码
下面展示的是书中的伪代码:
RADIXSORT
输入:一张有n个数的表L={a1,a2,a3....,an}和k位数字。
输出:按非降序排序的L
1.for j <- 1 to k
2. 准备10个空表L0,L1,...,L9
3. while L 非空
4. a <- L中的下一个元素;删除a。 //将L中的数分配到10个表
5. i <- a中的第j位数字了;将a加入表Li中
6. end while
7. L <- L0 //L0加入到L
8. for i <- 1 to 9
9. L <- L,Li
10. end for
11.end for
12.return L
上传代码之前先述说自己遇到的问题:
- 第一坑,求个十百千位时,原以为只用一个%号就足够了,后来发现每一位的公式都不太一样,具体,而且刚开始写的时候,直接用的10^j,那不是1234求十位就是1234%100=34,所以j是要去减1的,而且不能只用%
for (int j = 1; j <= k; j++) {
while (L != null && L.size() != 0) {
a = L.get(0);
L.remove(0);
if (j==1){
i = (int) (a % Math.pow(10, j));
}else if(j==2){
i = (int) (a / Math.pow(10, j-1)%10);
}else if(j==k){
i = (int) (a / Math.pow(10, j-1));
}else {
i = (int) (a / Math.pow(10, j-1)%10);
}
- 第二坑,伪代码8,9行,把L0,L1,…L9合并到L中之后是要清空L0,L1,…L9的,这一点伪代码中并没有写到,鬼知道我debug了多久,排序十位的时候,发现我明明存入一个数到L3,L3中怎么会出现3个数,才发觉是不是排序个位的时候L3合并到L之后没有清空导致原来的数字还存在着
for (int b = 0; b <= 9; b++) {
switch (b) {
case 0:
L.addAll(L0);
L0.removeAll(L0);
break;
case 1:
L.addAll(L1);
L1.removeAll(L1);
break;
case 2:
L.addAll(L2);
L2.removeAll(L2);
break;
case 3:
L.addAll(L3);
L3.removeAll(L3);
break;
case 4:
L.addAll(L4);
L4.removeAll(L4);
break;
case 5:
L.addAll(L5);
L5.removeAll(L5);
break;
case 6:
L.addAll(L6);
L6.removeAll(L6);
break;
case 7:
L.addAll(L7);
L7.removeAll(L7);
break;
case 8:
L.addAll(L8);
L8.removeAll(L8);
break;
case 9:
L.addAll(L9);
L9.removeAll(L9);
break;
}
}
- 第三坑,伪代码中4,5行,取出L中的下一个元素,于是我就用了一个for循环,但是每取出一个数,你是要从list中删除一个数的,就会导致你的u=0的时候,数组原来是8个,你取出的的确是第一个,但是新数组现在是7个,你u++之后,u=1了,就会从新数组取出第二个数,导致结果出错,我的解决方法是直接取0,删除一个之后不断取0删除0,那么就会总取第一个了
a = L.get(0);
L.remove(0);
下面展示的是Java的实现:
package com.sheye;
import java.util.ArrayList;
import java.util.List;
/**
* @author Sheye
* @date 2019-10-15 17:23
*/
public class RadixSort {
static int a;
static List<Integer> L = new ArrayList();
static List<Integer> L0 = new ArrayList();
static List<Integer> L1 = new ArrayList();
static List<Integer> L2 = new ArrayList();
static List<Integer> L3 = new ArrayList();
static List<Integer> L4 = new ArrayList();
static List<Integer> L5 = new ArrayList();
static List<Integer> L6 = new ArrayList();
static List<Integer> L7 = new ArrayList();
static List<Integer> L8 = new ArrayList();
static List<Integer> L9 = new ArrayList();
static void radixSort(int k) {
int i;
L.add(7467);
L.add(1247);
L.add(3275);
L.add(6792);
L.add(9187);
L.add(9134);
L.add(4675);
L.add(1239);
// for (int i :L) {
// System.out.println(i);
// }
for (int j = 1; j <= k; j++) {
while (L != null && L.size() != 0) {
//for (int u = 0; u < L.size(); u++) {
a = L.get(0);
L.remove(0);
if (j==1){
i = (int) (a % Math.pow(10, j));
}else if(j==2){
i = (int) (a / Math.pow(10, j-1)%10);
}else if(j==k){
i = (int) (a / Math.pow(10, j-1));
}else {
i = (int) (a / Math.pow(10, j-1)%10);
}
switch (i) {
case 0:
L0.add(a);
break;
case 1:
L1.add(a);
break;
case 2:
L2.add(a);
break;
case 3:
L3.add(a);
break;
case 4:
L4.add(a);
break;
case 5:
L5.add(a);
break;
case 6:
L6.add(a);
break;
case 7:
L7.add(a);
break;
case 8:
L8.add(a);
break;
case 9:
L9.add(a);
break;
}
//}
}
for (int b = 0; b <= 9; b++) {
switch (b) {
case 0:
L.addAll(L0);
L0.removeAll(L0);
break;
case 1:
L.addAll(L1);
L1.removeAll(L1);
break;
case 2:
L.addAll(L2);
L2.removeAll(L2);
break;
case 3:
L.addAll(L3);
L3.removeAll(L3);
break;
case 4:
L.addAll(L4);
L4.removeAll(L4);
break;
case 5:
L.addAll(L5);
L5.removeAll(L5);
break;
case 6:
L.addAll(L6);
L6.removeAll(L6);
break;
case 7:
L.addAll(L7);
L7.removeAll(L7);
break;
case 8:
L.addAll(L8);
L8.removeAll(L8);
break;
case 9:
L.addAll(L9);
L9.removeAll(L9);
break;
}
}
for (Integer list:L) {
System.out.print(list+",");
}
System.out.println();
}
}
public static void main (String[]args){
// System.out.println("请输入一个数字");
// Scanner sc = new Scanner(System.in);
// String str = sc.next();
// System.out.println("排序后的结果");
radixSort(4);
}
}
贴上运行结果
每一次循环排序的结果如下:
6792,9134,3275,4675,7467,1247,9187,1239,
9134,1239,1247,7467,3275,4675,9187,6792,
9134,9187,1239,1247,3275,7467,4675,6792,
1239,1247,3275,4675,6792,7467,9134,9187,
总结:我真的太水了,自认为自己不错,这么简单的一个代码,几乎是从下午5点做到了晚上10点,我有什么用?还有就是基本完成了实现,我是测试的时候直接给上数的位数的,但是可以添加一个scanner,输入你输入的是个几位数,也可以直接从数组中取出一个数,然后转化为字符串,用STRING里面的length方法,查看是几位数,再带入到实参中去,以后套用的时候也可以封装成面向对象,更好调用。