Merge sort implementation with various improvements
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
New contributor
add a comment |
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
New contributor
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
add a comment |
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
New contributor
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
java algorithm sorting mergesort
New contributor
New contributor
edited Dec 22 at 13:22
Vogel612♦
21.3k346128
21.3k346128
New contributor
asked Dec 22 at 13:15
SpookyBuster
113
113
New contributor
New contributor
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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 toarray
). 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.
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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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 toarray
). 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.
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
add a comment |
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 toarray
). 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.
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
add a comment |
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 toarray
). 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.
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 toarray
). 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.
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
add a comment |
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
add a comment |
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.
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
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