codebytes: Merge Sort Implementation with minor Improvements [Java]
1. Skip merge procedure if the elements in the two sorted halves to merge are already in ascending order (i.e. if firstHalf's end element <= secondHalf's first element so no merge is needed at all).
2. We can avoid copying back from auxiliary array every time
merge is called by interchanging the roles of original array and auxiliary array during recursion. (The final result will be stored in the auxiliary array.)
public static void merge(int[] orig, int[] aux, int start, int mid, int end) {
int i, j, z = start;
if(orig[mid] <= orig[mid+1])return; //Point #1
for(i=start, j = mid+1; i!=mid+1 || j!=end+1;){
if(i==mid+1) while(j!=end+1){ aux[z++] = orig[j++]; }
else if(j==end+1) while(i!=mid+1){ aux[z++] = orig[i++]; }
else if(orig[i]<=orig[j]) aux[z++] = orig[i++];
else aux[z++] = orig[j++];
}
}
public static void sort(int[] orig, int[] aux, int start, int end) {
if (start >= end) return;
int mid = (start + end) / 2;
sort(aux, orig, start, mid); //Point #2
sort(aux, orig, mid + 1, end);
merge(orig, aux, start, mid, end);
}
public static void main(String[] args) {
int array[] = {5, 4, 3, 2, 1};
int aux[] = new int[array.length];
System.arraycopy(array, 0, aux, 0, array.length); //Be careful, both arrays must be the same initially!
sort(array, aux, 0, array.length-1);
System.out.println(Arrays.toString(aux));
}
int array[] = {5, 4, 3, 2, 1};
int aux[] = new int[array.length];
System.arraycopy(array, 0, aux, 0, array.length); //Be careful, both arrays must be the same initially!
sort(array, aux, 0, array.length-1);
System.out.println(Arrays.toString(aux));
Bottom Up Merge Sort Java Implementation
Bottom up merge sort sorts the array without using recursion. It is 10% slower than the top down (recursive) mergesort. The idea is to start sorting the array elements from the start in groups of 2, 4, 8, 16, and so on (powers of two). So that the effect is the same as the recursive algorithm.
public static void merge(int[] orig, int[] aux, int start, int mid, int end) {
int i, j, z = start;
if(orig[mid] <= orig[mid+1])return;
for(i=start, j = mid+1; i!=mid+1 || j!=end+1;){
if(i==mid+1) while(j!=end+1){ aux[z++] = orig[j++]; }
else if(j==end+1) while(i!=mid+1){ aux[z++] = orig[i++]; }
else if(orig[i]<=orig[j]) aux[z++] = orig[i++];
else aux[z++] = orig[j++];
}
System.out.println(Arrays.toString(orig));
System.out.println("start = "+start+" mid = "+mid+" end = "+end);
System.out.println(Arrays.toString(aux)+"\n");
System.arraycopy(aux, start, orig, start, end-start+1);
}
public static void sort(int[] orig, int[] aux, int start, int end) {
int N = orig.length;
for (int sz = 1; sz < N; sz *= 2) {
for (int lo = 0; lo < N - sz; lo += sz + sz) {
merge(orig, aux, lo, lo + sz - 1, Math.min(lo + sz + sz - 1, N-1));
}
}
}
http://www.codebytes.in/2014/09/merge-sort-implementation-in-java.html
归并排序的非递归实现
对于非递归版的归并排序,一个需要注意的点是如果推进归并操作。根据递归实现归并排序的原理可以知道,第一次归并操作的步长是1,然后步长成指数级的增长,非递归实现归并排序也需要遵循这个原则。所以我们可以通过调整步长来推进归并操作。
public
static
void
mergeSortIterative(
int
[] nums){
if
(nums ==
null
|| nums.length <
2
)
return
;
int
[] tmp =
new
int
[nums.length];
int
step =
1
;
int
leftStart =
0
, leftEnd =
0
, rightStart =
0
, rightEnd =
0
;
for
(; step < nums.length; step *=
2
){
for
(leftStart =
0
; leftStart < nums.length - step; leftStart = rightEnd){
leftEnd = rightStart = leftStart + step;
rightEnd = rightStart + step;
if
(rightEnd > nums.length)
rightEnd = nums.length;
int
index =
0
;
while
(leftStart < leftEnd && rightStart < rightEnd)
if
(nums[leftStart] > nums[rightStart])
tmp[index++] = nums[rightStart++];
else
tmp[index++] = nums[leftStart++];
while
(leftStart < leftEnd){
nums[--rightStart] = nums[--leftEnd];
}
while
(index >
0
){
nums[--rightStart] = tmp[--index];
}
}
}
}
External Merge Sort:
http://massivealgorithms.blogspot.com/2014/03/merge-sort.html
Read full article from
codebytes: Merge Sort Implementation with minor Improvements [Java]