views:

187

answers:

3

Are there any resources on how the mergeSort used by Arrays.sort(Object[] a) is implemented? While it is documented quite good, I have a hard time understanding it (especially why the src and dest are are switched when mergeSort() get's recursively called).

+8  A: 

Here is the source of java.util.Arrays.

Actually, you have that source code in the JDK - just open java.util.Arrays in your IDE and the source code + the comments will appear. If you don't have an IDE, look at JDK_HOME\src.zip

Then, put it in your IDE and trace how it works.

  • put breakpoints (and run a program in debug mode)
  • use System.out.println(..)
  • change parts of it to see how they are reflected.
  • read the wikipedia article about merge sort
  • pay attention to this comment: // Recursively sort halves of dest into src
Bozho
It **appears** the OP already saw the source (since s/he mentions the fact that the `src` and `dest` arrays are switched when recursively called) but has a hard time understanding the logic.
Bart Kiers
hm, yes. I gave some pointers on how to understand it better.
Bozho
I could be wrong of course... Anyway, I was going to suggest the OP to use the *poor-man's debugger* (putting some System.out.println's in the algorithm), but you beat me to it!
Bart Kiers
:) it was in the original answer, but wasn't that much pointed out.
Bozho
Thanks, didn't know the sources were available in src.zip. I only read the class file which Eclipse opened but which I wasn't able to debug (which makes sense ^^). But with the source, I was able to modify the code, put in some breakpoints and finally realized how it works.
Helper Method
+1  A: 

This article could help you to understand mergesort better before you go into the (optimzed) libary code.

stacker
The library code is actually not really optimized, it's a misconception. I've had a serious issue with it on a 16-cores Mac / 20 GB of ram and huge datasets: it is mono-threaded. So 15 of my cores were idling. I had to rewrite a multi-threaded sort algo myself (I rewrote quicksort out of lazyness, for it's slightly easier than mergesort). So it's "optimized" when put back in the concept of the 90's and early 200x, where single-core CPUs where the norm :)
Webinator
A: 

I understand how the algorithm works, but what I don't understand why the recursion in the end always returns the dest array (switching dest and src on any recursive call). Here's the implementation:

       private static void mergeSort(Object[] src,
                                      Object[] dest,
                                      int low,
                                      int high,
                                      int off) {
            int length = high - low;

            // Insertion sort on smallest arrays
            if (length < INSERTIONSORT_THRESHOLD) {
                for (int i=low; i<high; i++)
                    for (int j=i; j>low &&
                             ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                        swap(dest, j, j-1);
                return;
            }


            // Recursively sort halves of dest into src
            int destLow  = low;
            int destHigh = high;
            low  += off;
            high += off;
            int mid = (low + high) >>> 1;
            mergeSort(dest, src, low, mid, -off);
            mergeSort(dest, src, mid, high, -off);

            // If list is already sorted, just copy from src to dest.  This is an
            // optimization that results in faster sorts for nearly ordered lists.
            if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
                System.arraycopy(src, low, dest, destLow, length);
                return;
            }

            // Merge sorted halves (now in src) into dest
            for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
                if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                    dest[i] = src[p++];
                else
                    dest[i] = src[q++];
            }
        }
Helper Method