Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# merge sort performance

just a quick note, this is not homework. I'm just trying to brush up on my algorithms. I'm playing around with MergeSort in C# and I've written a recursive method that can sort based on Generics:

class SortAlgorithms
{

    public T[] MergeSort<T> (T[] unsortedArray) where T : System.IComparable<T>
    {
        T[] left, right;
        int middle = unsortedArray.Length / 2;

        left = new T[middle];
        right = new T[unsortedArray.Length - middle];

        if (unsortedArray.Length <= 1)
            return unsortedArray;

        for (int i = 0; i < middle; i++)
        {
            left[i] = unsortedArray[i];
        }

        for (int i = middle; i < unsortedArray.Length; i++)
        {
            right[i - middle] = unsortedArray[i];
        }

        left = MergeSort(left);

        right = MergeSort(right);


        return Merge<T>(left, right);
    }

    private T[] Merge<T> (T[] left, T[] right) where T : System.IComparable<T>
    {
        T[] result = new T[left.Length + right.Length];

        int currentElement = 0;

        while (left.Length > 0 || right.Length > 0)
        {
            if (left.Length > 0 && right.Length > 0)
            {
                if (left[0].CompareTo(right[0]) < 0)
                {
                    result[currentElement] = left[0];
                    left = left.Skip(1).ToArray();
                    currentElement++;
                }
                else
                {
                    result[currentElement] = right[0];
                    right = right.Skip(1).ToArray();
                    currentElement++;
                }
            }
            else if (left.Length > 0)
            {
                result[currentElement] = left[0];
                left = left.Skip(1).ToArray();
                currentElement++;
            }
            else if (right.Length > 0)
            {
                result[currentElement] = right[0];
                right = right.Skip(1).ToArray();
                currentElement++;
            }
        }

        return result;
    }
}

This works but it is painfully slow. I've used System.Diagnostic.StopWatch to check performance against Array.Sort (which uses QuickSort algorithm) to compare against my MergeSort and the difference is so significant I'm wondering if maybe I'm implementing this wrong. Any comments?

like image 506
hobeau Avatar asked Aug 27 '12 19:08

hobeau


People also ask

What C is used for?

C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...

Is C language easy?

Compared to other languages—like Java, PHP, or C#—C is a relatively simple language to learn for anyone just starting to learn computer programming because of its limited number of keywords.

What is C in C language?

What is C? C is a general-purpose programming languagegeneral-purpose programming languageIn computer software, a general-purpose programming language (GPL) is a programming language designed to be used for building software in a wide variety of application domains, across a multitude of hardware configurations and operating systems.https://en.wikipedia.org › wiki › General-purpose_programmi...General-purpose programming language - Wikipedia created by Dennis Ritchie at the Bell Laboratories in 1972. It is a very popular language, despite being old. C is strongly associated with UNIX, as it was developed to write the UNIX operating system.

What is C full form?

History: The name C is derived from an earlier programming language called BCPL (Basic Combined Programming Language). BCPL had another language based on it called B: the first letter in BCPL.


2 Answers

I am not a C# programmer, but could the problem be the use of statements like this one?

left = left.Skip(1).ToArray();

This might be implemented in a way that forces a deep copy of the underlying array. If so, this would drop the performance of merge from O(n) to O(n2), immediately dropping the performance of the resulting merge sort from O(n log n) to O(n2).

(This is because the recurrence changes from

T(1) = O(1)

T(n) ≤ 2T(n / 2) + O(n)

which has solution T(n) = O(n log n), to

T(1) = O(1)

T(n) ≤ 2T(n / 2) + O(n2)

which has solution T(n) = O(n2).)

like image 127
templatetypedef Avatar answered Oct 06 '22 00:10

templatetypedef


You are constantly allocating memory in the form of intermediate arrays. Think in the direction of reusing the original array.

like image 24
Vitaliy Avatar answered Oct 06 '22 00:10

Vitaliy