sort array of integers lexicographically C++

前端 未结 12 1491
野的像风
野的像风 2021-02-02 13:53

I want to sort a large array of integers (say 1 millon elements) lexicographically.

Example:

input [] = { 100, 21 , 22 , 99 , 1  , 927 }
sorted[] = { 1           


        
12条回答
  •  执笔经年
    2021-02-02 14:23

    While some other answers here (Lightness's, notbad's) are already showing quite good code, I believe I can add one solution which might be more performant (since it requires neither division nor power in each loop; but it requires floating point arithmetic, which again might make it slow, and possibly inaccurate for large numbers):

    #include 
    #include 
    #include 
    
    // method taken from http://stackoverflow.com/a/1489873/671366
    template 
    int numDigits(T number)
    {
        int digits = 0;
        if (number < 0) digits = 1; // remove this line if '-' counts as a digit
        while (number) {
            number /= 10;
            digits++;
        }
        return digits;
    }
    
    bool lexiSmaller(int i1, int i2)
    {
        int digits1 = numDigits(i1);
        int digits2 = numDigits(i2);
    
        double val1 = i1/pow(10.0, digits1-1);
        double val2 = i2/pow(10.0, digits2-1);
    
        while (digits1 > 0 && digits2 > 0 && (int)val1 == (int)val2)
        {
            digits1--;
            digits2--;
            val1 = (val1 - (int)val1)*10;
            val2 = (val2 - (int)val2)*10;
        }
        if (digits1 > 0 && digits2 > 0)
        {
            return (int)val1 < (int)val2;
        }
        return (digits2 > 0);
    }
    
    
    int main(int argc, char* argv[])
    {
        // just testing whether the comparison function works as expected:
        assert (lexiSmaller(1, 100));
        assert (!lexiSmaller(100, 1));
        assert (lexiSmaller(100, 22));
        assert (!lexiSmaller(22, 100));
        assert (lexiSmaller(927, 99));
        assert (!lexiSmaller(99, 927));
        assert (lexiSmaller(1, 927));
        assert (!lexiSmaller(927, 1));
        assert (lexiSmaller(21, 22));
        assert (!lexiSmaller(22, 21));
        assert (lexiSmaller(22, 99));
        assert (!lexiSmaller(99, 22));
    
        // use the comparison function for the actual sorting:
        int input[] = { 100 , 21 , 22 , 99 , 1 ,927 };
        std::sort(&input[0], &input[5], lexiSmaller);
        std::cout << "sorted: ";
        for (int i=0; i<6; ++i)
        {
            std::cout << input[i];
            if (i<5)
            {
                std::cout << ", ";
            }
        }
        std::cout << std::endl;
        return 0;
    }
    

    Though I have to admit I haven't tested the performance yet.

提交回复
热议问题