该问题并未说明如何按字典排序顺序处理负整数。前面介绍的基于字符串的方法通常会将负值排在前面;例如,{ -123, -345, 0, 234, 78 } 将按该顺序保留。但如果应该忽略减号,则输出顺序应为 { 0, -123, 234, -345, 78 }。可以采用一种基于字符串的方法,通过有些繁琐的附加测试来生成该顺序。
在理论和代码上,使用比较两个整数的常用对数的小数部分的比较器可能更简单。也就是说,它将比较两个数字的以 10 为底的对数的尾数。基于对数的比较器将比基于字符串的比较器运行得更快或更慢,这取决于 CPU 的浮点性能规范和实现的质量。
此答案末尾显示的 java 代码包括两个基于对数的比较器: alogCompare
和slogCompare
. 前者忽略符号,因此会从 { -123, -345, 0, 234, 78 } 产生 { 0, -123, 234, -345, 78 }。
接下来显示的数字组是 java 程序产生的输出。
“dar rand”部分显示生成的随机数据数组dar
。它读取然后向下读取,每行 5 个元素。请注意,数组sar
、lara
和lars
最初是 的未排序副本dar
。
“dar 排序”部分是dar
在通过排序之后Arrays.sort(dar);
。
“sar lex”部分显示sar
用 排序后的数组Arrays.sort(sar,lexCompare);
,其中lexCompare
类似于Comparator
Jason Cohen 的答案中所示。
“lar s log”部分显示lars
了按 排序后的数组,说明了一种基于对数的方法,它给出与 do和其他基于字符串的方法Arrays.sort(lars,slogCompare);
相同的顺序。lexCompare
“lar a log”部分显示lara
了排序后的数组Arrays.sort(lara,alogCompare);
,说明了一种忽略减号的基于对数的方法。
dar rand -335768 115776 -9576 185484 81528
dar rand 79300 0 3128 4095 -69377
dar rand -67584 9900 -50568 -162792 70992
dar sort -335768 -162792 -69377 -67584 -50568
dar sort -9576 0 3128 4095 9900
dar sort 70992 79300 81528 115776 185484
sar lex -162792 -335768 -50568 -67584 -69377
sar lex -9576 0 115776 185484 3128
sar lex 4095 70992 79300 81528 9900
lar s log -162792 -335768 -50568 -67584 -69377
lar s log -9576 0 115776 185484 3128
lar s log 4095 70992 79300 81528 9900
lar a log 0 115776 -162792 185484 3128
lar a log -335768 4095 -50568 -67584 -69377
lar a log 70992 79300 81528 -9576 9900
Java 代码如下所示。
// Code for "How can I sort numbers lexicographically?" - jw - 2 Jul 2014
import java.util.Random;
import java.util.Comparator;
import java.lang.Math;
import java.util.Arrays;
public class lex882954 {
// Comparator from Jason Cohen's answer
public static Comparator<Integer> lexCompare = new Comparator<Integer>(){
public int compare( Integer x, Integer y ) {
return x.toString().compareTo( y.toString() );
}
};
// Comparator that uses "abs." logarithms of numbers instead of strings
public static Comparator<Integer> alogCompare = new Comparator<Integer>(){
public int compare( Integer x, Integer y ) {
Double xl = (x==0)? 0 : Math.log10(Math.abs(x));
Double yl = (y==0)? 0 : Math.log10(Math.abs(y));
Double xf=xl-xl.intValue();
return xf.compareTo(yl-yl.intValue());
}
};
// Comparator that uses "signed" logarithms of numbers instead of strings
public static Comparator<Integer> slogCompare = new Comparator<Integer>(){
public int compare( Integer x, Integer y ) {
Double xl = (x==0)? 0 : Math.log10(Math.abs(x));
Double yl = (y==0)? 0 : Math.log10(Math.abs(y));
Double xf=xl-xl.intValue()+Integer.signum(x);
return xf.compareTo(yl-yl.intValue()+Integer.signum(y));
}
};
// Print array before or after sorting
public static void printArr(Integer[] ar, int asize, String aname) {
int j;
for(j=0; j < asize; ++j) {
if (j%5==0)
System.out.printf("%n%8s ", aname);
System.out.printf(" %9d", ar[j]);
}
System.out.println();
}
// Main Program -- to test comparators
public static void main(String[] args) {
int j, dasize=15, hir=99;
Random rnd = new Random(12345);
Integer[] dar = new Integer[dasize];
Integer[] sar = new Integer[dasize];
Integer[] lara = new Integer[dasize];
Integer[] lars = new Integer[dasize];
for(j=0; j < dasize; ++j) {
lara[j] = lars[j] = sar[j] = dar[j] = rnd.nextInt(hir) *
rnd.nextInt(hir) * (rnd.nextInt(hir)-44);
}
printArr(dar, dasize, "dar rand");
Arrays.sort(dar);
printArr(dar, dasize, "dar sort");
Arrays.sort(sar, lexCompare);
printArr(sar, dasize, "sar lex");
Arrays.sort(lars, slogCompare);
printArr(lars, dasize, "lar s log");
Arrays.sort(lara, alogCompare);
printArr(lara, dasize, "lar a log");
}
}