How can I sort numbers lexicographically?

前端 未结 14 936
半阙折子戏
半阙折子戏 2020-12-09 04:56

Here is the scenario.

I am given an array \'A\' of integers. The size of the array is not fixed. The function that I am supposed to write may be called once with an

14条回答
  •  情歌与酒
    2020-12-09 05:36

    The question doesn't indicate how to treat negative integers in the lexicographic collating order. The string-based methods presented earlier typically will sort negative values to the front; eg, { -123, -345, 0, 234, 78 } would be left in that order. But if the minus signs were supposed to be ignored, the output order should be { 0, -123, 234, -345, 78 }. One could adapt a string-based method to produce that order by somewhat-cumbersome additional tests.

    It may be simpler, in both theory and code, to use a comparator that compares fractional parts of common logarithms of two integers. That is, it will compare the mantissas of base 10 logarithms of two numbers. A logarithm-based comparator will run faster or slower than a string-based comparator, depending on a CPU's floating-point performance specs and on quality of implementations.

    The java code shown at the end of this answer includes two logarithm-based comparators: alogCompare and slogCompare. The former ignores signs, so would produce { 0, -123, 234, -345, 78 } from { -123, -345, 0, 234, 78 }.

    The number-groups shown next are the output produced by the java program.

    The “dar rand” section shows a random-data array dar as generated. It reads across and then down, 5 elements per line. Note, arrays sar, lara, and lars initially are unsorted copies of dar.

    The “dar sort” section is dar after sorting via Arrays.sort(dar);.

    The “sar lex” section shows array sar after sorting with Arrays.sort(sar,lexCompare);, where lexCompare is similar to the Comparator shown in Jason Cohen's answer.

    The “lar s log” section shows array lars after sorting by Arrays.sort(lars,slogCompare);, illustrating a logarithm-based method that gives the same order as do lexCompare and other string-based methods.

    The “lar a log” section shows array lara after sorting by Arrays.sort(lara,alogCompare);, illustrating a logarithm-based method that ignores minus signs.

    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 is shown below.

    // 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 lexCompare = new Comparator(){
            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 alogCompare = new Comparator(){
            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 slogCompare = new Comparator(){
            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");
        }
    }
    

提交回复
热议问题