views:

232

answers:

3

Hi everybody!

I spend some time implementing a quicksort algorithm in C#. After finishing I compared the speed of my implementation and C#'s Array.Sort-Method.

I just compare speed working on random int arrays.

Here's my implementation:

static void QuickSort(int[] data, int left, int right)
{
    int i = left - 1,
        j = right;

    while (true)
    {
        int d = data[left];
        do i++; while (data[i] < d);
        do j--; while (data[j] > d);

        if (i < j) 
        {
            int tmp = data[i];
            data[i] = data[j];
            data[j] = tmp;
        }
        else
        {
            if (left < j)    QuickSort(data, left, j);
            if (++j < right) QuickSort(data, j, right);
            return;
        }
    }
}

Performance (when sorting an random int[] with length of 100000000):
   - my algorithm: 14.21 seconds
   - .Net Array<int>.Sort: 14.84 seconds

Does anyone know how to implement my algorithm even faster?
Or can anyone provide a faster implementation (need not be a quicksort!) which my run faster?

Note:
   - please no algorithms which use multiple cores/processors to improve perrformance
   - only valid C# source code

I will test the performance of the provided algorithms within a few minutes if I'm online.

EDIT:
Do you think using a ideal sorting network for parts containing less than 8 value would improve performance?

+3  A: 

Does anyone know how to implement my algorithm even faster?

I was able to shave 10% off the execution time by converting your code to use pointers.

    public unsafe static void UnsafeQuickSort(int[] data)
    {
        fixed (int* pdata = data)
        {
            UnsafeQuickSortRecursive(pdata, 0, data.Length - 1);
        }
    }

    private unsafe static void UnsafeQuickSortRecursive(int* data, int left, int right)
    {
        int i = left - 1;
        int j = right;

        while (true)
        {
            int d = data[left];
            do i++; while (data[i] < d);
            do j--; while (data[j] > d);

            if (i < j)
            {
                int tmp = data[i];
                data[i] = data[j];
                data[j] = tmp;
            }
            else
            {
                if (left < j) UnsafeQuickSortRecursive(data, left, j);
                if (++j < right) UnsafeQuickSortRecursive(data, j, right);
                return;
            }
        }
    }
Brian Gideon
there is a little bug, but really nice upgrade (+1), 1.1 seconds faster on my hardware!
youllknow
Doesn't this clash with the "safe" requirement in the title?
Gabe
It's a bit difficult to say... this is simple enough too...I just wanted to be sure that I don't get any high optimized C/C++ codes.
youllknow
@Gabe: I thought about that too before I posted. I was not really sure if "safe" was synonomous with "stable". But, considering that the quick sort is not stable that is probably a moot point anyway. I decided to go ahead and post anyway.
Brian Gideon
@youllknow: I fixed the bug. Thanks for bring that to my attention.
Brian Gideon
I would probably have the top level function either not have the left/right args or do some bounds checking before the call.
Dolphin
@Dolphin: Good idea.
Brian Gideon
+5  A: 

Binary insertion sort almost always wins for short runs (~10 items). It's often better than an ideal sorting network because of the simplified branching structure.

Dual pivot quicksort is faster than quicksort. The linked paper contains a Java implementation that you could presumably adapt.

If you're only sorting integers, a radix sort will likely be faster still on long arrays.

Rex Kerr
A: 

Take a look at Shear Sort and Odd-Event Transposition sort: http://www.cs.rit.edu/~atk/Java/Sorting/sorting.html and http://home.westman.wave.ca/~rhenry/sort/.

There's a C# implementation of Shear Sort here: http://www.codeproject.com/KB/recipes/cssorters.aspx.

The examples are in Java but that's awfully close to C#. They're parallel sorts because they run faster on multiple cores but still should be very fast.

ebpower