问题
假设有一位工程师架设了一个设备来记录给定时间段内某条忙碌的调整公路上所有车辆的车牌号,他希望知道总共有多少辆不同的车辆经过了这段高速公路。简单方案就是将所有车辆号排序,然后遍历找出所有不同的车牌号的数量,车牌号由数字和字母组成,因此一般都将它们表示为字符串。车牌号的长度一般都是相同的,这种情况在排序应用中很常见——比如电话号码、银行账号、IP地址等都是典型的定长字符串。
低位优先排序字符串
package algorithm.string;
import java.util.Arrays;
import java.util.Random;
import java.util.UUID;
public class SortStrLSD {
public static void main(String[] args) {
Random r = new Random();
String[] a = new String[5];
for (int i = 0; i < 5; i++) {
String s = UUID.randomUUID().toString().replace("-", "").substring(0, 6);
a[i] = s;
}
System.out.println(Arrays.toString(a));
sort(a, 6);
System.out.println(Arrays.toString(a));
}
public static void sort(String[] a, int w) {
// 通过前W个字符将a[]排序
int N = a.length;
int R = 256;
String[] aux = new String[N];
for (int d = w - 1; d >= 0; d--) {
// 根据第d个字符用键索引计数法排序
int[] count = new int[R + 1];
//计算出现频率
for (String s : a) count[s.charAt(d) + 1]++;
// 将频率转换为索引
for (int r = 0; r < R; r++) count[r + 1] += count[r];
// 将元素分类
for (String s : a) aux[count[s.charAt(d)]++] = s;
// 回写
System.array(aux, 0, a, 0, N);
}
}
}
高位优先排序字符串
package algorithm.string;
import java.util.Arrays;
import java.util.Random;
import java.util.UUID;
public class SortStrMSD {
private static int R = 256;//基数
private static final int M = 15;//小数组的切换阈值
private static String[] aux;// 数据分类的辅助数组
private static int charAt(String s, int d) {
if (d < s.length()) return s.charAt(d); else return -1;
}
public static void sort(String[] a) {
int N = a.length;
aux = new String[N];
sort(a, 0, N - 1, 0);
}
private static void sort(String[] a, int lo, int hi, int d) {
//以第d个字符为键将a[lo]至a[hi]排序
if (hi <= lo + M) {
sortMSD(a, lo, hi, d);
return;
}
int[] count = new int[R + 2];//计算频率
for (int i = lo; i <= hi; i++) count[charAt((a[i]), d) + 2]++;
for (int r = 0; r < R + 1; r++) count[r + 1] += count[r];//将频率转换为索引
for (int i = lo; i <= hi; i++) aux[count[charAt(a[i], d) + 1]++] = a[i];//数据分类
for (int i = lo; i <= hi; i++) a[i] = aux[i - lo];//回写
for (int r = 0; r < R; r++) {
sort(a, lo + count[r], lo + count[r + 1] - 1, d + 1);
}
}
private static void exch(Object[] a, int i, int j) {
Object swap = a[i];
a[i] = a[j];
a[j] = swap;
}
public static void sortMSD(String[] a, int lo, int hi, int d) {
for (int i = lo; i <= hi; i++) {
for (int j = i; j > lo && less(a[j], a[j-1], d); j--) {
exch(a, j, j - 1);
}
}
}
private static boolean less(String v, String w, int d) {
return v.substring(d).compareTo(w.substring(d)) < 0;
}
public static void main(String[] args) {
Random r = new Random();
String[] a = new String[5];
for (int i = 0; i < 5; i++) {
String s = UUID.randomUUID().toString().replace("-", "").substring(0, 6);
a[i] = s;
}
System.out.println(Arrays.toString(a));
sort(a);
System.out.println(Arrays.toString(a));
}
}