Search code examples
c#quicksort

How can this DualPivot Quicksort be made better / faster


How the title already says, im asking how I can make my code faster or better. Right now im having the problem that my Dual Pivot Quicksort is much much slower than a normal Quicksort and also cant handle large numbers as well. Right now im just gonna put in the code for the Method but if you want I can post the Main methode too, so you can see my inputs.

public static List<int> sort(List<int> input, bool start)
{
    if (input.Count > 1)
    {
        int LP = input[0];
        int RP = input[input.Count - 1];
        List<int> lessLP = new List<int>();
        List<int> greatRP = new List<int>();
        List<int> betweenLPRP = new List<int>();
        if (LP > RP)
        {
            int sp = LP;
            LP = RP;
            RP = sp;
        }

        for (int i = 1; i < input.Count - 1; i++)
        {
            if (input[i] < LP)
            {
                lessLP.Add(input[i]);
            }

            else if (input[i] > RP)
            {
                greatRP.Add(input[i]);
            }

            else if (input[i] >= LP & input[i] <= RP)
            {
                betweenLPRP.Add(input[i]);
            }
        }
        List<int> end = new List<int>();

        lessLP = sort(lessLP, false);
        greatRP = sort(greatRP, false);
        betweenLPRP = sort(betweenLPRP, false);
        input.Clear();

        foreach (var x in lessLP)
        {
            end.Add(x);
        }
        lessLP.Clear();
        end.Add(LP);
        foreach (var x in betweenLPRP)
        {
            end.Add(x);
        }
        betweenLPRP.Clear();
        end.Add(RP);
        foreach (var x in greatRP)
        {
            end.Add(x);
        }
        greatRP.Clear();
        return end;
    }
    return input;
}

Thanks for helping already. btw Sorry for the uncommented code

Edit: Ok after some feedback I tried to get this code https://cs.stackexchange.com/questions/24092/dual-pivot-quicksort-reference-implementation as c# to work.

but everytime I run this code now I get an StackOverflowException

        public static void quicksort(ref int[] arr, int left, int right)
        {
            if (right > left)
            {
                if (arr[left] > arr[right]) swap(ref arr, left, right);
                int p = arr[left], q = arr[right];

                int l = left + 1, g = right - 1, k = 1; 
                while(k <= g)
                {
                    if (arr[k] < p)
                    {
                        swap(ref arr, k, l);
                        l++;
                    }

                    else if (arr[k] >= q)
                    {
                        while (arr[g] > q && k < g) g--;
                        swap(ref arr, k, g);
                        g--;
                        if(arr[k] < p)
                        {
                            swap(ref arr, k, l);
                            l++;
                        }
                    }
                    k++;
                }
                l--; g++;

                swap(ref arr, left, l);
                swap(ref arr, right, g);
                quicksort(ref arr, left, l - 1);
                quicksort(ref arr, l + 1, g - 1);
                quicksort(ref arr, g + 1, right);
            }
        }

        public static void swap(ref int[] arr, int i, int j)
        {
            int tmp = arr[i];
            arr[i] = arr[j];
            arr[j] = tmp;
        }

Solution

  • You have a typo in your translation of the code from that reference.

    On this line:

    int l = left + 1, g = right - 1, k = 1;

    That last 1 (one) that you have should instead be an l (lower-case L).

    Incidentally, since arrays are reference types by definition in c#, the ref modifier on the arr argument is unnecessary. That is only needed if you wish to replace the entire parameter wholesale from within the method (as in arr = new ...) and have that change reflected in the caller. This goes for both quicksort and swap. Here, ref only makes the code less efficient.

    Another minor point is that the referenced code (and yours) has some inefficiencies where it calls swap with identical i and j arguments - doesn't affect validity, though, only speed.