snippetjavaMinor
Memory/performance of merge sort code
Viewed 0 times
mergeperformancememorycodesort
Problem
I wrote up merge sort code for some late night snack. I have gotten it working, but was just looking learn if I was missing anything in terms of efficiency. Could this code be significantly improved in terms of efficiency (space/time/unnecessary checks)?
```
package com.komal.sort;
import java.util.Arrays;
import java.util.Date;
public class MergeSort {
static int a[]= {1,2,7,4,5,8,12,54,23,66,22,312,65,23,65,867,222,21,1000};
public static void main(String[] args) {
System.out.println(new Date());
System.out.println("input length: "+ a.length);
int [] result =new MergeSort().mergeSort("start", a);
System.out.println("Result: "+Arrays.toString(result));
System.out.println("\nResult array size: "+ result.length);
System.out.println("\n"+new Date());
}
public int[] mergeSort( String subTree, int [] a)
{
System.out.println("MergeSort.mergeSort():"+subTree+" inputs:"+ Arrays.toString(a));
if(a.length>1)
{
int[] leftArray= Arrays.copyOfRange(a, 0, (a.length/2));
int[] rightArray= Arrays.copyOfRange(a, (a.length/2), a.length);
return merge(mergeSort("left", leftArray), mergeSort("right",rightArray));
}
return a;
}
public int[] merge(int[] leftArray, int[] rightArray)
{
int[] input = new int[leftArray.length+ rightArray.length];
int left=0;
int i=0;
int right=0;
while(left+right!= leftArray.length + rightArray.length)
{
if(left>=leftArray.length ){
input[i]= rightArray[right];
i++;
right++;
}
else if(right>=rightArray.length ){
input[i]= leftArray[left];
i++;
left++;
}
else{
if(leftArray[left]<rightArray[right])
```
package com.komal.sort;
import java.util.Arrays;
import java.util.Date;
public class MergeSort {
static int a[]= {1,2,7,4,5,8,12,54,23,66,22,312,65,23,65,867,222,21,1000};
public static void main(String[] args) {
System.out.println(new Date());
System.out.println("input length: "+ a.length);
int [] result =new MergeSort().mergeSort("start", a);
System.out.println("Result: "+Arrays.toString(result));
System.out.println("\nResult array size: "+ result.length);
System.out.println("\n"+new Date());
}
public int[] mergeSort( String subTree, int [] a)
{
System.out.println("MergeSort.mergeSort():"+subTree+" inputs:"+ Arrays.toString(a));
if(a.length>1)
{
int[] leftArray= Arrays.copyOfRange(a, 0, (a.length/2));
int[] rightArray= Arrays.copyOfRange(a, (a.length/2), a.length);
return merge(mergeSort("left", leftArray), mergeSort("right",rightArray));
}
return a;
}
public int[] merge(int[] leftArray, int[] rightArray)
{
int[] input = new int[leftArray.length+ rightArray.length];
int left=0;
int i=0;
int right=0;
while(left+right!= leftArray.length + rightArray.length)
{
if(left>=leftArray.length ){
input[i]= rightArray[right];
i++;
right++;
}
else if(right>=rightArray.length ){
input[i]= leftArray[left];
i++;
left++;
}
else{
if(leftArray[left]<rightArray[right])
Solution
Unnecessary array creation
The
The reduced array creation will optimize the performance,
though it will not change the order of complexity.
Inefficient merging
The conditions throughout the merge step are not organized efficiently.
First of all, for each target element, this condition is evaluated:
Instead of using
But in any case, this condition is not very expressive,
it just reveals that we haven't reached the end of one of the arrays,
and inside the loop body we still need to check again if reached the end of one of them.
A more efficient and clearer way to organize the conditions is to use 3 loops:
Naming
The
mergeSort method creates leftArray and rightArray, but it doesn't really need to.merge could use a single input array with start, middle and end indexes.The reduced array creation will optimize the performance,
though it will not change the order of complexity.
Inefficient merging
The conditions throughout the merge step are not organized efficiently.
First of all, for each target element, this condition is evaluated:
left + right != leftArray.length + rightArray.lengthInstead of using
leftArray.length + rightArray.length, you could use the target length that is already known without addition.But in any case, this condition is not very expressive,
it just reveals that we haven't reached the end of one of the arrays,
and inside the loop body we still need to check again if reached the end of one of them.
A more efficient and clearer way to organize the conditions is to use 3 loops:
while (left < leftArray.length && right < rightArray.length) {
if (leftArray[left] < rightArray[right]) {
input[i++] = leftArray[left++];
} else {
input[i++] = rightArray[right++];
}
}
while (left < leftArray.length) {
input[i++] = leftArray[left++];
}
while (right < rightArray.length) {
input[i++] = rightArray[right++];
}Naming
input is not a good name for an array that in fact stores the output of a method.Code Snippets
left + right != leftArray.length + rightArray.lengthwhile (left < leftArray.length && right < rightArray.length) {
if (leftArray[left] < rightArray[right]) {
input[i++] = leftArray[left++];
} else {
input[i++] = rightArray[right++];
}
}
while (left < leftArray.length) {
input[i++] = leftArray[left++];
}
while (right < rightArray.length) {
input[i++] = rightArray[right++];
}Context
StackExchange Code Review Q#131128, answer score: 5
Revisions (0)
No revisions yet.