4
\$\begingroup\$

I would like your opinion on my Java implementation of the merge sort algorithm on an integer array, since I'm not really into algorithms I'd like to know from you if this is a correct implementation and if it can be improved somehow.

For example, it requires a lot of space for the sub arrays, but this should be normal for the merge sort as it is not space constant. I tested it and it seems to work.

private int[] mergeSort(int[] array) {
 if (array.length == 1) return array;
 int start = 0;
 int end = array.length;
 int middle = (end-start)/2;
 int[] left = Arrays.copyOfRange(array, start, middle);
 int[] right = Arrays.copyOfRange(array, middle, end);
 int[] sortedLeft = mergeSort(left);
 int[] sortedRight = mergeSort(right);
 return merge(sortedLeft, sortedRight);
}
private int[] merge(int[] first, int[] second) {
 int[] result = new int[first.length + second.length];
 int posFirst = 0;
 int posSecond = 0;
 int resultPos = 0;
 while (resultPos < result.length) {
 if (posFirst == first.length) {
 result[resultPos++] = second[posSecond++];
 }
 else if (posSecond == second.length) {
 result[resultPos++] = first[posFirst++];
 }
 else if (first[posFirst] > second[posSecond]) {
 result[resultPos++] = second[posSecond++];
 } else {
 result[resultPos++] = first[posFirst++];
 }
 }
 return result;
}
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Feb 20, 2015 at 11:03
\$\endgroup\$

3 Answers 3

3
\$\begingroup\$

MergeSort is a nice sort algorithm because the concepts are relatively simple, even the recursion makes sense, and it all just 'fits'.

You have done a good job at describing the algorithm through your code. Putting performance aside, I think you did a good job. Small items to consider:

  1. the methods do not use any instance state information, so they should probably both be static methods, and should the main mergeSort method there be public too?

  2. The last two conditions in the cascading if/else statement are:

     else if (first[posFirst] > second[posSecond]) {
     result[resultPos++] = second[posSecond++];
     } else {
     result[resultPos++] = first[posFirst++];
     }
    

    I would prefer to see the logic a bit clearer in the sense that first should be handled first, and it can be done like:

    else if (first[posFirst] <= second[posSecond]) {
     result[resultPos++] = first[posFirst++];
    } else {
     result[resultPos++] = second[posSecond++];
    }
    
  3. One final nit-pick, you have posFirst, and posSecond, but then you called the other position resultPos? Shouldn't that be posResult?

As for the performance, your system creates many new arrays. Even though the logic of the sort algorithm is very apparent the way you have done it, the reality is that performance can be improved massively by creating one large temporary array and performing the merge in small parts from the source array, to the temp array, then swapping them to do the next larger merge.

Wikipedia has an algorithm written in C that does the bottom-up merge sort using two arrays, one is a temp array. Now that you have the algorithm done I encourage you to do a better implementation of the Wikipedia's code.... it is really ugly, and could do with a review ;-)

answered Feb 20, 2015 at 12:28
\$\endgroup\$
0
4
\$\begingroup\$

one of the things you can do is pass in the original array to merge and use that as result:

 return merge(sortedLeft, sortedRight, array);
}

and

private int[] merge(int[] first, int[] second, int[] result) {
 int posFirst = 0;
 int posSecond = 0;
 int resultPos = 0;

This reduces the space needed during the merge portion. Though at the cost of modifying the array the user put in.

answered Feb 20, 2015 at 11:18
\$\endgroup\$
0
3
\$\begingroup\$

I want to point out that you've made a fairly common "mistake" that could rear its ugly head if you decided to transition this code to bottom-up, for instance.

Your midpoint is calculated incorrectly:

int middle = (end-start)/2;

It should be:

int middle = (end+start)/2;
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
answered Feb 20, 2015 at 17:57
\$\endgroup\$
2
  • \$\begingroup\$ Good spotting there. I wonder if this is a partial copy/paste problem from the 'famous' bug which is solved with: start + (end - start)/2 : Extra, Extra - Read All About It: Nearly All Binary Searches and Mergesorts are Broken \$\endgroup\$ Commented Feb 21, 2015 at 0:15
  • \$\begingroup\$ Ok thank you, I didn't know about this bug but it makes a lot of sense now. \$\endgroup\$ Commented Feb 22, 2015 at 7:22

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.