Merge sort implementation with various improvements












2














So I was working on merge sort today, and was trying to speed it up. I would like your opinion on the implementation and if it's possible to make it faster. Besides that I was wondering if there are any mistakes that i am making code wise, things that are considered a bad practice.



I like making algorithms for fun, and then when i make them I always try to improve them. One thing that I have noticed which i couldn't wrap my head around was that when you give a reverse sorted array as input it works faster than when you don't.



public static void mergeSort(int array) {
mergeDivider(array,0,array.length-1);
}

private static void mergeDivider(int array, int lowBound, int highBound) {
if(lowBound < highBound) {
int middle = (lowBound + highBound)/2;

if((highBound - lowBound) <= 43){
//Found online that insertion sort is faster for n <= 43
mergeSortInsertionSortSpeedUp(array,lowBound,highBound);
} else {
//Normal divide and conquer
mergeDivider(array, lowBound, middle);
mergeDivider(array, middle + 1, highBound);

if(array[middle] > array[middle + 1]){
mergeSortMerger(array, lowBound, middle, highBound);
}
}
}
}

//Merge method
private static void mergeSortMerger(int array, int lowBound, int middle, int highBound) {
//Doesn't make seperate copies for left and right only makes a temporary array
int left_index = lowBound, right_index = middle + 1,temp_index = 0;
int temp_holder = new int[highBound - lowBound + 1];

while(left_index <= middle && right_index <= highBound){
if(array[left_index] < array[right_index]){
temp_holder[temp_index++] = array[left_index++];
} else {
temp_holder[temp_index++] = array[right_index++];
}
}

while(left_index <= middle){
temp_holder[temp_index++] = array[left_index++];
}
while(right_index <= highBound){
temp_holder[temp_index++] = array[right_index++];
}

//Put everything in the original array
for(int x = lowBound, k = 0; x <=highBound;x++,k++){
array[x] = temp_holder[k];
}
}

private static void mergeSortInsertionSortSpeedUp(int array, int left, int right){
for(int x = left; x <= right;x++){
int temp = array[x];
int before = x - 1;
while(before >= left && array[before] > temp){
array[before+1] = array[before];
before--;
}
array[before+1] = temp;
}
}









share|improve this question









New contributor




SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • was trying to speed [up merge-sort] Advice: be explicit about the base-line, think about/design a benchmark, look around if there's something useful (framework, test-set(-generator), whole benchmark). If possible, set a performance goal. For tape sort, there used to be multi-way merge-sorts: care to argue relevance thereof?
    – greybeard
    Dec 22 at 17:43










  • (faster with reverse sorted input is most probably due to branch prediction.)
    – greybeard
    Dec 22 at 21:13
















2














So I was working on merge sort today, and was trying to speed it up. I would like your opinion on the implementation and if it's possible to make it faster. Besides that I was wondering if there are any mistakes that i am making code wise, things that are considered a bad practice.



I like making algorithms for fun, and then when i make them I always try to improve them. One thing that I have noticed which i couldn't wrap my head around was that when you give a reverse sorted array as input it works faster than when you don't.



public static void mergeSort(int array) {
mergeDivider(array,0,array.length-1);
}

private static void mergeDivider(int array, int lowBound, int highBound) {
if(lowBound < highBound) {
int middle = (lowBound + highBound)/2;

if((highBound - lowBound) <= 43){
//Found online that insertion sort is faster for n <= 43
mergeSortInsertionSortSpeedUp(array,lowBound,highBound);
} else {
//Normal divide and conquer
mergeDivider(array, lowBound, middle);
mergeDivider(array, middle + 1, highBound);

if(array[middle] > array[middle + 1]){
mergeSortMerger(array, lowBound, middle, highBound);
}
}
}
}

//Merge method
private static void mergeSortMerger(int array, int lowBound, int middle, int highBound) {
//Doesn't make seperate copies for left and right only makes a temporary array
int left_index = lowBound, right_index = middle + 1,temp_index = 0;
int temp_holder = new int[highBound - lowBound + 1];

while(left_index <= middle && right_index <= highBound){
if(array[left_index] < array[right_index]){
temp_holder[temp_index++] = array[left_index++];
} else {
temp_holder[temp_index++] = array[right_index++];
}
}

while(left_index <= middle){
temp_holder[temp_index++] = array[left_index++];
}
while(right_index <= highBound){
temp_holder[temp_index++] = array[right_index++];
}

//Put everything in the original array
for(int x = lowBound, k = 0; x <=highBound;x++,k++){
array[x] = temp_holder[k];
}
}

private static void mergeSortInsertionSortSpeedUp(int array, int left, int right){
for(int x = left; x <= right;x++){
int temp = array[x];
int before = x - 1;
while(before >= left && array[before] > temp){
array[before+1] = array[before];
before--;
}
array[before+1] = temp;
}
}









share|improve this question









New contributor




SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.




















  • was trying to speed [up merge-sort] Advice: be explicit about the base-line, think about/design a benchmark, look around if there's something useful (framework, test-set(-generator), whole benchmark). If possible, set a performance goal. For tape sort, there used to be multi-way merge-sorts: care to argue relevance thereof?
    – greybeard
    Dec 22 at 17:43










  • (faster with reverse sorted input is most probably due to branch prediction.)
    – greybeard
    Dec 22 at 21:13














2












2








2







So I was working on merge sort today, and was trying to speed it up. I would like your opinion on the implementation and if it's possible to make it faster. Besides that I was wondering if there are any mistakes that i am making code wise, things that are considered a bad practice.



I like making algorithms for fun, and then when i make them I always try to improve them. One thing that I have noticed which i couldn't wrap my head around was that when you give a reverse sorted array as input it works faster than when you don't.



public static void mergeSort(int array) {
mergeDivider(array,0,array.length-1);
}

private static void mergeDivider(int array, int lowBound, int highBound) {
if(lowBound < highBound) {
int middle = (lowBound + highBound)/2;

if((highBound - lowBound) <= 43){
//Found online that insertion sort is faster for n <= 43
mergeSortInsertionSortSpeedUp(array,lowBound,highBound);
} else {
//Normal divide and conquer
mergeDivider(array, lowBound, middle);
mergeDivider(array, middle + 1, highBound);

if(array[middle] > array[middle + 1]){
mergeSortMerger(array, lowBound, middle, highBound);
}
}
}
}

//Merge method
private static void mergeSortMerger(int array, int lowBound, int middle, int highBound) {
//Doesn't make seperate copies for left and right only makes a temporary array
int left_index = lowBound, right_index = middle + 1,temp_index = 0;
int temp_holder = new int[highBound - lowBound + 1];

while(left_index <= middle && right_index <= highBound){
if(array[left_index] < array[right_index]){
temp_holder[temp_index++] = array[left_index++];
} else {
temp_holder[temp_index++] = array[right_index++];
}
}

while(left_index <= middle){
temp_holder[temp_index++] = array[left_index++];
}
while(right_index <= highBound){
temp_holder[temp_index++] = array[right_index++];
}

//Put everything in the original array
for(int x = lowBound, k = 0; x <=highBound;x++,k++){
array[x] = temp_holder[k];
}
}

private static void mergeSortInsertionSortSpeedUp(int array, int left, int right){
for(int x = left; x <= right;x++){
int temp = array[x];
int before = x - 1;
while(before >= left && array[before] > temp){
array[before+1] = array[before];
before--;
}
array[before+1] = temp;
}
}









share|improve this question









New contributor




SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











So I was working on merge sort today, and was trying to speed it up. I would like your opinion on the implementation and if it's possible to make it faster. Besides that I was wondering if there are any mistakes that i am making code wise, things that are considered a bad practice.



I like making algorithms for fun, and then when i make them I always try to improve them. One thing that I have noticed which i couldn't wrap my head around was that when you give a reverse sorted array as input it works faster than when you don't.



public static void mergeSort(int array) {
mergeDivider(array,0,array.length-1);
}

private static void mergeDivider(int array, int lowBound, int highBound) {
if(lowBound < highBound) {
int middle = (lowBound + highBound)/2;

if((highBound - lowBound) <= 43){
//Found online that insertion sort is faster for n <= 43
mergeSortInsertionSortSpeedUp(array,lowBound,highBound);
} else {
//Normal divide and conquer
mergeDivider(array, lowBound, middle);
mergeDivider(array, middle + 1, highBound);

if(array[middle] > array[middle + 1]){
mergeSortMerger(array, lowBound, middle, highBound);
}
}
}
}

//Merge method
private static void mergeSortMerger(int array, int lowBound, int middle, int highBound) {
//Doesn't make seperate copies for left and right only makes a temporary array
int left_index = lowBound, right_index = middle + 1,temp_index = 0;
int temp_holder = new int[highBound - lowBound + 1];

while(left_index <= middle && right_index <= highBound){
if(array[left_index] < array[right_index]){
temp_holder[temp_index++] = array[left_index++];
} else {
temp_holder[temp_index++] = array[right_index++];
}
}

while(left_index <= middle){
temp_holder[temp_index++] = array[left_index++];
}
while(right_index <= highBound){
temp_holder[temp_index++] = array[right_index++];
}

//Put everything in the original array
for(int x = lowBound, k = 0; x <=highBound;x++,k++){
array[x] = temp_holder[k];
}
}

private static void mergeSortInsertionSortSpeedUp(int array, int left, int right){
for(int x = left; x <= right;x++){
int temp = array[x];
int before = x - 1;
while(before >= left && array[before] > temp){
array[before+1] = array[before];
before--;
}
array[before+1] = temp;
}
}






java algorithm sorting mergesort






share|improve this question









New contributor




SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.











share|improve this question









New contributor




SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









share|improve this question




share|improve this question








edited Dec 22 at 13:22









Vogel612

21.3k346128




21.3k346128






New contributor




SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.









asked Dec 22 at 13:15









SpookyBuster

113




113




New contributor




SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.





New contributor





SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.






SpookyBuster is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.












  • was trying to speed [up merge-sort] Advice: be explicit about the base-line, think about/design a benchmark, look around if there's something useful (framework, test-set(-generator), whole benchmark). If possible, set a performance goal. For tape sort, there used to be multi-way merge-sorts: care to argue relevance thereof?
    – greybeard
    Dec 22 at 17:43










  • (faster with reverse sorted input is most probably due to branch prediction.)
    – greybeard
    Dec 22 at 21:13


















  • was trying to speed [up merge-sort] Advice: be explicit about the base-line, think about/design a benchmark, look around if there's something useful (framework, test-set(-generator), whole benchmark). If possible, set a performance goal. For tape sort, there used to be multi-way merge-sorts: care to argue relevance thereof?
    – greybeard
    Dec 22 at 17:43










  • (faster with reverse sorted input is most probably due to branch prediction.)
    – greybeard
    Dec 22 at 21:13
















was trying to speed [up merge-sort] Advice: be explicit about the base-line, think about/design a benchmark, look around if there's something useful (framework, test-set(-generator), whole benchmark). If possible, set a performance goal. For tape sort, there used to be multi-way merge-sorts: care to argue relevance thereof?
– greybeard
Dec 22 at 17:43




was trying to speed [up merge-sort] Advice: be explicit about the base-line, think about/design a benchmark, look around if there's something useful (framework, test-set(-generator), whole benchmark). If possible, set a performance goal. For tape sort, there used to be multi-way merge-sorts: care to argue relevance thereof?
– greybeard
Dec 22 at 17:43












(faster with reverse sorted input is most probably due to branch prediction.)
– greybeard
Dec 22 at 21:13




(faster with reverse sorted input is most probably due to branch prediction.)
– greybeard
Dec 22 at 21:13










1 Answer
1






active

oldest

votes


















1
















  • Mandatory stability note: the sequence



        if(array[left_index] < array[right_index]){
    temp_holder[temp_index++] = array[left_index++];
    } else {
    temp_holder[temp_index++] = array[right_index++];
    }


    causes loss of stability (equal elements are merged in the wrong order).




  • The code still does unnecessary copying (from tmp back to array). It is unnecessary because it can be avoided. Allocate a temporary array once, then



        merge_sort subrange 0 of arr into corresponding subrange of tmp
    merge_sort subrange 1 of arr into corresponding subrange of tmp
    merge subranges from tmp to arr



  • The insertion sort implementation is suboptimal. Testing two conditions in



        while(before >= left && array[before] > temp)


    can be avoided. Take a look at the Alex Stepanov's technique (he is talking about quicksort, but the first 4 methods, which you are are only interested in, are equally applicable to your case).



  • The algorithms of this kind generally look better at the semi-open ranges. Try to rewrite the code with the assumption that highBound does not belong to the range.







share|improve this answer























  • Thank you for you response, I was wondering what you meant with your second point. I vaguely understand what you mean, but not completely. I get that I might be able to do it more efficiently, but everytime i have tried so far, it didn't really do anything.
    – SpookyBuster
    Dec 23 at 15:06











Your Answer





StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");

StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});






SpookyBuster is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210170%2fmerge-sort-implementation-with-various-improvements%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1
















  • Mandatory stability note: the sequence



        if(array[left_index] < array[right_index]){
    temp_holder[temp_index++] = array[left_index++];
    } else {
    temp_holder[temp_index++] = array[right_index++];
    }


    causes loss of stability (equal elements are merged in the wrong order).




  • The code still does unnecessary copying (from tmp back to array). It is unnecessary because it can be avoided. Allocate a temporary array once, then



        merge_sort subrange 0 of arr into corresponding subrange of tmp
    merge_sort subrange 1 of arr into corresponding subrange of tmp
    merge subranges from tmp to arr



  • The insertion sort implementation is suboptimal. Testing two conditions in



        while(before >= left && array[before] > temp)


    can be avoided. Take a look at the Alex Stepanov's technique (he is talking about quicksort, but the first 4 methods, which you are are only interested in, are equally applicable to your case).



  • The algorithms of this kind generally look better at the semi-open ranges. Try to rewrite the code with the assumption that highBound does not belong to the range.







share|improve this answer























  • Thank you for you response, I was wondering what you meant with your second point. I vaguely understand what you mean, but not completely. I get that I might be able to do it more efficiently, but everytime i have tried so far, it didn't really do anything.
    – SpookyBuster
    Dec 23 at 15:06
















1
















  • Mandatory stability note: the sequence



        if(array[left_index] < array[right_index]){
    temp_holder[temp_index++] = array[left_index++];
    } else {
    temp_holder[temp_index++] = array[right_index++];
    }


    causes loss of stability (equal elements are merged in the wrong order).




  • The code still does unnecessary copying (from tmp back to array). It is unnecessary because it can be avoided. Allocate a temporary array once, then



        merge_sort subrange 0 of arr into corresponding subrange of tmp
    merge_sort subrange 1 of arr into corresponding subrange of tmp
    merge subranges from tmp to arr



  • The insertion sort implementation is suboptimal. Testing two conditions in



        while(before >= left && array[before] > temp)


    can be avoided. Take a look at the Alex Stepanov's technique (he is talking about quicksort, but the first 4 methods, which you are are only interested in, are equally applicable to your case).



  • The algorithms of this kind generally look better at the semi-open ranges. Try to rewrite the code with the assumption that highBound does not belong to the range.







share|improve this answer























  • Thank you for you response, I was wondering what you meant with your second point. I vaguely understand what you mean, but not completely. I get that I might be able to do it more efficiently, but everytime i have tried so far, it didn't really do anything.
    – SpookyBuster
    Dec 23 at 15:06














1












1








1








  • Mandatory stability note: the sequence



        if(array[left_index] < array[right_index]){
    temp_holder[temp_index++] = array[left_index++];
    } else {
    temp_holder[temp_index++] = array[right_index++];
    }


    causes loss of stability (equal elements are merged in the wrong order).




  • The code still does unnecessary copying (from tmp back to array). It is unnecessary because it can be avoided. Allocate a temporary array once, then



        merge_sort subrange 0 of arr into corresponding subrange of tmp
    merge_sort subrange 1 of arr into corresponding subrange of tmp
    merge subranges from tmp to arr



  • The insertion sort implementation is suboptimal. Testing two conditions in



        while(before >= left && array[before] > temp)


    can be avoided. Take a look at the Alex Stepanov's technique (he is talking about quicksort, but the first 4 methods, which you are are only interested in, are equally applicable to your case).



  • The algorithms of this kind generally look better at the semi-open ranges. Try to rewrite the code with the assumption that highBound does not belong to the range.







share|improve this answer
















  • Mandatory stability note: the sequence



        if(array[left_index] < array[right_index]){
    temp_holder[temp_index++] = array[left_index++];
    } else {
    temp_holder[temp_index++] = array[right_index++];
    }


    causes loss of stability (equal elements are merged in the wrong order).




  • The code still does unnecessary copying (from tmp back to array). It is unnecessary because it can be avoided. Allocate a temporary array once, then



        merge_sort subrange 0 of arr into corresponding subrange of tmp
    merge_sort subrange 1 of arr into corresponding subrange of tmp
    merge subranges from tmp to arr



  • The insertion sort implementation is suboptimal. Testing two conditions in



        while(before >= left && array[before] > temp)


    can be avoided. Take a look at the Alex Stepanov's technique (he is talking about quicksort, but the first 4 methods, which you are are only interested in, are equally applicable to your case).



  • The algorithms of this kind generally look better at the semi-open ranges. Try to rewrite the code with the assumption that highBound does not belong to the range.








share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 22 at 18:57

























answered Dec 22 at 18:42









vnp

38.5k13097




38.5k13097












  • Thank you for you response, I was wondering what you meant with your second point. I vaguely understand what you mean, but not completely. I get that I might be able to do it more efficiently, but everytime i have tried so far, it didn't really do anything.
    – SpookyBuster
    Dec 23 at 15:06


















  • Thank you for you response, I was wondering what you meant with your second point. I vaguely understand what you mean, but not completely. I get that I might be able to do it more efficiently, but everytime i have tried so far, it didn't really do anything.
    – SpookyBuster
    Dec 23 at 15:06
















Thank you for you response, I was wondering what you meant with your second point. I vaguely understand what you mean, but not completely. I get that I might be able to do it more efficiently, but everytime i have tried so far, it didn't really do anything.
– SpookyBuster
Dec 23 at 15:06




Thank you for you response, I was wondering what you meant with your second point. I vaguely understand what you mean, but not completely. I get that I might be able to do it more efficiently, but everytime i have tried so far, it didn't really do anything.
– SpookyBuster
Dec 23 at 15:06










SpookyBuster is a new contributor. Be nice, and check out our Code of Conduct.










draft saved

draft discarded


















SpookyBuster is a new contributor. Be nice, and check out our Code of Conduct.













SpookyBuster is a new contributor. Be nice, and check out our Code of Conduct.












SpookyBuster is a new contributor. Be nice, and check out our Code of Conduct.
















Thanks for contributing an answer to Code Review Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


Use MathJax to format equations. MathJax reference.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210170%2fmerge-sort-implementation-with-various-improvements%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Сан-Квентин

8-я гвардейская общевойсковая армия

Алькесар