Mergesort not sorting correctly - java

I tried to implement merge sort in Java using the code below. The mergeSort() method is supposed to be a recursive method that repeatedly divides the array into smaller sections, while the merge() method takes 2 sections of the array that has already been sorted and merges them into a single sorted section.
Here's the code:
class MergeSort{
public static void mergeSort(int[] array){
mergeSort(array, 0, array.length-1);
}
public static void mergeSort(int[] array, int start, int end){
int mid = (start + end)/2;
if (end > start) {
mergeSort(array, start, mid);
mergeSort(array, mid + 1, end);
merge(array, start, end, mid + 1);
}
}
public static void merge(int[] array, int start, int end, int mid){
int length = end - start + 1,length1 = mid- start, length2 = end - mid + 1, index1 = start, index2 = mid, sortedindex = 0;
boolean cont = true;
int[] sortedArray = new int[length];
while (cont){
if (array[index1] > array[index2]){
sortedArray[sortedindex] = array[index2];
index2++;
} else{
sortedArray[sortedindex] = array[index1];
index1++;
}
sortedindex++;
//reached the end of one array, dump the rest of the remaining array in the sorted array
if (index1 >= length1){
for (index2 = index2; index2 < length2; index2++){
sortedArray[sortedindex] = array[index2];
sortedindex++;
}
cont = false;
} else if (index2 >= length2){
for (index1 =index1; index1 < length1; index1++){
sortedArray[sortedindex] = array[index1];
sortedindex++;
}
cont = false;
}
}
//copy the sorted array into the main array
for (int i = 0; i <= length - 1; i++){
array[start+i] = sortedArray[i];
}
}
}
public class Main {
public static void main(String[] args) {
// write your code here
Scanner scanner = new Scanner(System.in);
scanner.useDelimiter("\n");
Random random = new Random();
int length = scanner.nextInt();
int[] array = new int[length];
for (int i = 0; i < length;i++){
array[i] = random.nextInt(5000);
//System.out.println(array[i]);
}
MergeSort.mergeSort(array);
for (int i: array){
System.out.println(i);
}
}
}
The main class then generates an array with a user-defined length, populates it with random integers, and passes it to mergeSort().
Unfortunately the program outputs an array where the first few elements are sorted correctly, but the rest are zeros. e.g. given a randomly generated array {3291, 2879, 3078, 3609, 3534, 3922, 2793, 1098, 472, 1800}, the program outputs {472, 2879, 3291, 0, 0, 0, 0, 0, 0, 0}, with the number of correctly sorted elements in the output differing from run to run.
I can't seem to figure out what's wrong with my code. Any help would be greatly appreciated :)

while loop should close earlier.
public static void merge1(int[] array, int start, int end, int mid) {
int length = end - start + 1;
int[] sortedArray = new int[length];
int index1 = start;
int index2 = mid + 1;
int sortedindex = 0;
while (index1 <= mid && index2 <= end) {
if (array[index1] < array[index2]) {
sortedArray[sortedindex++] = array[index1++];
} else {
sortedArray[sortedindex++] = array[index2++];
}
}
// reached the end of one array, dump the rest of the remaining array in the
// sorted array
while (index1 <= mid) {
sortedArray[sortedindex++] = array[index1++];
}
while (index2 <= end) {
sortedArray[sortedindex++] = array[index2++];
}
// copy the sorted array into the main array
for (int i = 0; i <= length - 1; i++) {
array[start + i] = sortedArray[i];
}
}

Related

Why do we use two different loop variables while sorting an array using merge sort?

I was learning to merge sort an integer array, when I noticed that while copying the sorted array elements to the original array, we need two separate loop variables to run simultaneously, while the values at those indices are copied to the original array. Here is the code for reference:
class MergeSort {
public static void sort(int arr[], int si, int ei, int mid) {
int merged[] = new int[ei - si + 1];
int index1 = si; // tracks the first array
int index2 = mid + 1; // tracks the second array
int i = 0;
while (index1 <= mid && index2 <= ei) {
if (arr[index1] <= arr[index2]) {
merged[i++] = arr[index1++];
} else {
merged[i++] = arr[index2++];
}
} // end of while
while (index1 <= mid) {
merged[i++] = arr[index1++];
}
while (index2 <= ei) {
merged[i++] = arr[index2++];
}
// to copy merged[] to arr[]
int j = si;
for (i = 0; i < merged.length; i++, j++) {
arr[j] = merged[i];
}
} // end sort()
public static void divide(int arr[], int si, int ei) {
// base case
if (si >= ei) {
return;
} // end of base case
int mid = si + (ei - si) / 2; // same as (ei-si)/2 but with less space complexity
divide(arr, si, mid);
divide(arr, mid + 1, ei);
sort(arr, si, ei, mid);
} // end of divide
public static void main(String args[]) {
int arr[] = { 1, 8, 0, 7, -4 };
int n = arr.length;
divide(arr, 0, n - 1);
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
} // end of for
} // end of main
} // end of class
Notice that while copying the values of the array merged[] to the array arr[], we are using two separate variables i and j. I did try using only one loop variable, which went like:
for (int i = 0; i < arr.length; i++) {
arr[i] = merged[i];
}
but received an incorrect output. If anyone knows why we need two separate variables for the operation, please let me know. Thank you :)
You could use a single variable in this final loop, but you must add the offset of the start of the slice in the destination array:
for (int i = 0; i < arr.length; i++) {
arr[si + i] = merged[i];
}

I made a MergeSort method with the firstHalf and secondHalf Method; index 0 ~ middle, middle+1 ~ end. However, this calls the StackOverFlow Error

public static void mergeSort(int[] data) {
int[] left = firstHalf(data);
int[] right = secondHalf(data);
if (data.length > 1) {
mergeSort(left);
mergeSort(right);
merge(data, left, right);
}
}
public static void merge(int[] data, int[] left, int[] right) {
int tempArraySize = data.length;
int mergedNumbers[] = new int[tempArraySize]; //Temp array to take the sorted array
int mergePos;
int leftPos;
int rightPos;
int middle = data.length / 2;
mergePos = 0;
leftPos = 0; // 0 index
rightPos = middle + 1; //j is middle index
while (leftPos <= middle && rightPos <= data.length - 1) {
if (left[leftPos] < right[rightPos]) {
mergedNumbers[mergePos] = left[leftPos];
leftPos++;
} else {
mergedNumbers[mergePos] = right[rightPos];
rightPos++;
}
mergePos++;
}
// when the right half array finishes sorting
while (leftPos <= middle) {
mergedNumbers[mergePos] = left[leftPos];
leftPos++;
mergePos++;
}
// when the left half array finishes sorting
while (rightPos <= data.length - 1) {
mergedNumbers[mergePos] = right[rightPos];
rightPos++;
mergePos++;
}
// give value to the original array
for (mergePos = 0; mergePos < tempArraySize; ++mergePos) {
data[leftPos + mergePos] = mergedNumbers[mergePos];
}
}
public static int[] firstHalf(int[] data) {
int[] tempFirst = new int[(data.length / 2) + 1];
for (int i = 0; i <= data.length / 2; i++) {
tempFirst[i] = data[i];
}
return tempFirst;
}
public static int[] secondHalf(int[] data) {
int[] tempSecond = new int[(data.length / 2) + 1];
for (int i = (data.length / 2) + 1; i < data.length; i++) { // Middle to the end
for (int j = 0; j <= data.length / 2; j++) {
tempSecond[j] = data[i];
}
}
return tempSecond;
}
This is what I made.
My mergeSort method makes an error java.lang.StackOverflowError
What mistakes I made?
I made the firstHalf and secondHalf methods to get the index 0 ~ middle and middle+1 ~ end.
Those methods are made to get the value from the original 'data' Array.
The merge method is as same as the common MergeSort code.
Do I have to build a base case in the mergeSort method?
With this approach, it is simpler to return merged arrays. It would be faster to do a one time allocation of a temporary array, and use indexing to merge data between the two arrays rather than creating temporary arrays and copy data. Fixes noted in comments.
public static int[] mergeSort(int[] data) { // fix
int[] left = firstHalf(data);
int[] right = secondHalf(data);
if(data.length < 2) // change
return data; // fix
left = mergeSort(left); // fix
right = mergeSort(right); // fix
return merge(left, right); // fix
}
public static int[] merge(int[] left, int[] right) { // fix
int mergedNumbers [] = new int[left.length+right.length]; // fix
int mergePos = 0; // fix
int leftPos = 0; // fix
int rightPos = 0; // fix
while (leftPos < left.length && rightPos < right.length) { // fix
if (left[leftPos] < right[rightPos]) {
mergedNumbers[mergePos] = left[leftPos];
leftPos++;
} else {
mergedNumbers[mergePos] = right[rightPos];
rightPos++;
}
mergePos++;
}
while (leftPos < left.length) { // fix
mergedNumbers[mergePos] = left[leftPos];
leftPos++;
mergePos++;
}
while (rightPos < right.length) { // fix
mergedNumbers[mergePos] = right[rightPos];
rightPos++;
mergePos++;
}
return mergedNumbers; // fix
}
public static int[] firstHalf(int[] data) {
int j = (data.length/2); // fix
int[] tempFirst = new int[j]; // fix
for(int i = 0; i < tempFirst.length; i++) // fix
tempFirst[i] = data[i];
return tempFirst;
}
public static int[] secondHalf(int[] data) {
int j = (data.length/2); // fix
int[] tempSecond = new int[data.length-j]; // fix
for(int i = 0; i < tempSecond.length; i++) // fix
tempSecond[i] = data[i+j]; // fix
return tempSecond;
}
The wiki article has a somewhat optimized approach for top down merge sort:
https://en.wikipedia.org/wiki/Merge_sort#Top-down_implementation
The problems in your code come from the confusing convention to specify ranges with included boundaries. You should instead consider the upper bound to be excluded: this would avoid the numerous +1/-1 adjustments required for the included convention, some of which are inconsistent in your code:
leftHalf creates an array with length (data.length / 2) + 1, including the element at offset mid = data.length / 2. This is what the merge method expects, but is not optimal as it would make unbalanced halves for even sized arrays, and more problematically would return a 2 element slice for a 2 element array, which causes an infinite recursion and explains the Stack Overflow exception you get.
rightHalf also creates an array with length (data.length / 2) + 1, which is incorrect, the length should be array with lengthdata.length - ((data.length / 2) + 1)`, which would be an empty array for a 2 element array.
Furthermore, rightHalf uses two nested for loops to copy the values from the argument array, which is incorrect.
your index range into the right array is incorrect in the merge method.
the index into data is incorrect in data[leftPos + mergePos] = mergedNumbers[mergePos]; it should be just:
data[mergePos] = mergedNumbers[mergePos];
Here is a modified version, with a less error prone convention:
// sort elements in data in place
public static void mergeSort(int[] data) {
if (data.length > 1) {
int[] left = firstHalf(data);
int[] right = secondHalf(data);
mergeSort(left);
mergeSort(right);
merge(data, left, right);
}
}
public static void merge(int[] data, int[] left, int[] right) {
int leftLength = left.length;
int rightLength = right.length;
int length = leftLength + rightLength;
int mergedNumbers[] = new int[length]; //Temp array to received the merged array
int leftPos = 0;
int rightPos = 0;
int mergePos = 0;
while (leftPos < leftLength && rightPos < rightLength) {
if (left[leftPos] <= right[rightPos]) {
mergedNumbers[mergePos] = left[leftPos];
leftPos++;
mergePos++;
} else {
mergedNumbers[mergePos] = right[rightPos];
rightPos++;
mergePos++;
}
}
// copy the remaining entries in the left half
while (leftPos < leftLength) {
mergedNumbers[mergePos] = left[leftPos];
leftPos++;
mergePos++;
}
// copy the remaining entries in the right half
while (rightPos < rightLength) {
mergedNumbers[mergePos] = right[rightPos];
rightPos++;
mergePos++;
}
// copy the values back to the original array
for (mergePos = 0; mergePos < length; mergePos++) {
data[mergePos] = mergedNumbers[mergePos];
}
}
public static int[] firstHalf(int[] data) {
int leftLength = data.length / 2;
int[] tempFirst = new int[leftLength];
for (int i = 0; i < leftLength; i++) {
tempFirst[i] = data[i];
}
return tempFirst;
}
public static int[] secondHalf(int[] data) {
int leftLength = data.length / 2;
int rightLength = data.length - leftLength;
int[] tempSecond = new int[rightLength];
for (int i = 0; i < rightLength; i++) {
tempSecond[i] = data[LeftLength + i];
}
return tempSecond;
}

StackOverFlow occuring in divide and conquer problem : maximum subArray

I was trying to resolve the maximum subArray sum problem with the divide and conquer approach but a runTime error (StackOverFlow) occured and I have no idea how to handle it, I think it's occuring just because of my recursive calls. Here is my approach (the error occured at the first recursive line):
class Solution {
public int maxSubArray(int[] nums){
int length = nums.length;
int middle = length / 2;
if(length == 1) {
return nums[0];
}
int[] starting = Arrays.copyOfRange(nums, 0, middle+1);
int[] ending = Arrays.copyOfRange(nums, middle +1, length);
int left = maxSubArray(starting);
int right = maxSubArray(ending);
int crossing = computeCrossingSum(starting,ending);
int result = Math.max(left,right);
int finalResult = Math.max(result,crossing);
return finalResult;
}
public int computeCrossingSum (int[] left, int[]right){
int leftS =Integer.MIN_VALUE;
int rightS =Integer.MIN_VALUE;
int leftIndex;
int rightIndex;
int sumS = 0;
for(int i = left.length -1 ; i>=0 ; i--) {
sumS += left[i];
if (sumS > leftS) {
leftS = sumS;
leftIndex = i;
}
}
int sumA = 0;
for(int i = 0 ; i< right.length ; i++){
sumA+=right[i];
if (sumA > rightS){
rightS = sumA;
leftIndex = i;
}
}
int crossingSum = leftS+rightS;
return crossingSum;
}
}
The middle + 1 in the recursive call never allow the array size to be 1, so the stop condition is never met. Remove the + 1
int[] starting = Arrays.copyOfRange(nums, 0, middle);
int[] ending = Arrays.copyOfRange(nums, middle, length);

splitting array using recursion java

I am trying to spit an int array and add up the elements but im getting errors. Here is my code. I can't figure it out.
int arraySize = 10;
int[] numsToSum = new int[arraySize];
for (int i = 0; i < arraySize; i++)
{
numsToSum[i] = i * 3;
System.out.println(numsToSum[i]);
}
int sum3 = sumArray3(numsToSum, 0, arraySize - 1);
System.out.println(sum3);
public static int sumArray3(int [] array, int start, int end)
{
int results = 0;
int mid = (start + end)/2;
if(array.length > 0)
{
results += sumArray3(array, start + 1, mid) + sumArray3(array, mid +1, end);
}
return results;
You don't have a recursion termination condition, in this case i'd assume you want to check if the start and end counters for the array are the same. Check the code below.
class StackOv {
public static void main(String[] args) {
int arraySize = 10;
int[] numsToSum = new int[arraySize];
for (int i = 0; i < arraySize; i++)
{
numsToSum[i] = i * 3;
System.out.println(numsToSum[i]);
}
int sum3 = sumArray3(numsToSum, 0, arraySize - 1);
System.out.println(sum3);
}
public static int sumArray3(int [] array, int start, int end)
{
int results = 0;
if(start == end)
return array[start];
int mid = (start + end)/2;
if(array.length > 0) {
results += sumArray3(array, start, mid) + sumArray3(array, mid +1, end);
}
return results;
}
}
I finally figured it out. Thanks for your help. I didn't have a base like you said.
public static int sumArray3(int [] array, int start, int end)
{
int results = 0;
int mid = (start + end)/2;
if(start < end)
{
results += sumArray3(array, start, mid) + sumArray3(array, mid +1, end);
}
else
results = array[start];
return results;
}
It looks like you don't have a "base-case", where you return a solid value. Your function as-is will always return 0.
At a guess, I would say you should start by changing it so that you check whether start+1 <= end and if so, returning your current value; if not returning the value at that index, with an else:
else {
results = array[start];
}

Merge Sort Java

I am trying to make a merge sort method, but it keeps on giving the wrong sorts. Where do I have change to make it actually sort the array? What part of the code has to be different? Thank you for your time.
public static void mergeSort(int[] array, int left, int lHigh, int right, int rHigh) {
int elements = (rHigh - lHigh +1) ;
int[] temp = new int[elements];
int num = left;
while ((left <= lHigh) && (right <= rHigh)){
if (a[left] <= array[right]) {
temp[num] = array[left];
left++;
}
else {
temp[num] = array[right];
right++;
}
num++;
}
while (left <= right){
temp[num] = array[left]; // I'm getting an exception here, and is it because of the num???
left += 1;
num += 1;
}
while (right <= rHigh) {
temp[num] = array[right];
right += 1;
num += 1;
}
for (int i=0; i < elements; i++){
array[rHigh] = temp[rHigh];
rHigh -= 1;
}
EDIT: now the mergeSort doesn't really sort the numbers, can someone tell me where it specifically is? especially when I print the "Testing merge sort" part.
First of all, I'm assuming this is academic rather than practical, since you're not using a built in sort function. That being said, here's some help to get you moving in the right direction:
Usually, one can think of a merge sort as two different methods: a merge() function that merges two sorted lists into one sorted list, and mergeSort() which recursively breaks the list into single element lists. Since a single element list is sorted already, you then merge all the lists together into one big sorted list.
Here's some off-hand pseudo-code:
merge(A, B):
C = empty list
While A and B are not empty:
If the first element of A is smaller than the first element of B:
Remove first element of A.
Add it to the end of C.
Otherwise:
Remove first element of B.
Add it to the end of C.
If A or B still contains elements, add them to the end of C.
mergeSort(A):
if length of A is 1:
return A
Split A into two lists, L and R.
Q = merge(mergeSort(L), mergeSort(R))
return Q
Maybe that'll help clear up where you want to go.
If not, there's always MergeSort at wikipedia.
Additional:
To help you out, here are some comments inline in your code.
public static void mergeSort(int[] array, int left, int lHigh, int right, int rHigh) {
// what do lHigh and rHigh represent?
int elements = (rHigh - lHigh +1) ;
int[] temp = new int[elements];
int num = left;
// what does this while loop do **conceptually**?
while ((left <= lHigh) && (right <= rHigh)){
if (a[left] <= a[right]) {
// where is 'pos' declared or defined?
temp[pos] = a[left];
// where is leftLow declared or defined? Did you mean 'left' instead?
leftLow ++;
}
else {
temp[num] = a[right];
right ++;
}
num++;
}
// what does this while loop do **conceptually**?
while (left <= right){
// At this point, what is the value of 'num'?
temp[num] = a[left];
left += 1;
num += 1;
}
while (right <= rHigh) {
temp[num] = a[right];
right += 1;
num += 1;
}
// Maybe you meant a[i] = temp[i]?
for (int i=0; i < elements; i++){
// what happens if rHigh is less than elements at this point? Could
// rHigh ever become negative? This would be a runtime error if it did
a[rHigh] = temp[rHigh];
rHigh -= 1;
}
I'm purposefully being vague so you think about the algorithm. Try inserting your own comments into the code. If you can write what is conceptually happening, then you may not need Stack Overflow :)
My thoughts here are that you are not implementing this correctly. This is because it looks like you're only touching the elements of the array only once (or close to only once). This means you have a worst case scenario of O(N) Sorting generally takes at least O(N * log N) and from what I know, the simpler versions of merge sort are actually O(N^2).
More:
In the most simplistic implementation of merge sort, I would expect to see some sort of recursion in the mergeSort() method. This is because merge sort is generally defined recursively. There are ways to do this iteratively using for and while loops, but I definitely don't recommend it as a learning tool until you get it recursively.
Honestly, I suggest taking either my pseudo-code or the pseudo-code you may find in a wikipedia article to implement this and start over with your code. If you do that and it doesn't work correctly still, post it here and we'll help you work out the kinks.
Cheers!
And finally:
// Precondition: array[left..lHigh] is sorted and array[right...rHigh] is sorted.
// Postcondition: array[left..rHigh] contains the same elements of the above parts, sorted.
public static void mergeSort(int[] array, int left, int lHigh, int right, int rHigh) {
// temp[] needs to be as large as the number of elements you're sorting (not half!)
//int elements = (rHigh - lHigh +1) ;
int elements = rHigh - left;
int[] temp = new int[elements];
// this is your index into the temp array
int num = left;
// now you need to create indices into your two lists
int iL = left;
int iR = right;
// Pseudo code... when you code this, make use of iR, iL, and num!
while( temp is not full ) {
if( left side is all used up ) {
copy rest of right side in.
make sure that at the end of this temp is full so the
while loop quits.
}
else if ( right side is all used up) {
copy rest of left side in.
make sure that at the end of this temp is full so the
while loop quits.
}
else if (array[iL] < array[iR]) { ... }
else if (array[iL] >= array[iR]) { ... }
}
}
public class MergeSort {
public static void main(String[] args) {
int[] arr = {5, 4, 7, 2, 3, 1, 6, 2};
print(arr);
new MergeSort().sort(arr, 0, arr.length - 1);
}
private void sort(int[] arr, int lo, int hi) {
if (lo < hi) {
int mid = (lo + hi) / 2;
sort(arr, lo, mid); // recursive call to divide the sub-list
sort(arr, mid + 1, hi); // recursive call to divide the sub-list
merge(arr, lo, mid, hi); // merge the sorted sub-lists.
print(arr);
}
}
private void merge(int[] arr, int lo, int mid, int hi) {
// allocate enough space so that the extra 'sentinel' value
// can be added. Each of the 'left' and 'right' sub-lists are pre-sorted.
// This function only merges them into a sorted list.
int[] left = new int[(mid - lo) + 2];
int[] right = new int[hi - mid + 1];
// create the left and right sub-list for merging into original list.
System.arraycopy(arr, lo, left, 0, left.length - 1);
System.arraycopy(arr, mid + 1, right, 0, left.length - 1);
// giving a sentinal value to marking the end of the sub-list.
// Note: The list to be sorted is assumed to contain numbers less than 100.
left[left.length - 1] = 100;
right[right.length - 1] = 100;
int i = 0;
int j = 0;
// loop to merge the sorted sequence from the 2 sub-lists(left and right)
// into the main list.
for (; lo <= hi; lo++) {
if (left[i] <= right[j]) {
arr[lo] = left[i];
i++;
} else {
arr[lo] = right[j];
j++;
}
}
}
// print the array to console.
private static void print(int[] arr) {
System.out.println();
for (int i : arr) {
System.out.print(i + ", ");
}
}
}
Here's another!
private static int[] mergeSort(int[] input){
if (input.length == 1)
return input;
int length = input.length/2;
int[] left = new int[length];
int[] right = new int[input.length - length];
for (int i = 0; i < length; i++)
left[i] = input[i];
for (int i = length; i < input.length; i++)
right[i-length] = input[i];
return merge(mergeSort(left),mergeSort(right));
}
private static int[] merge(int[] left, int[] right){
int[] merged = new int[left.length+right.length];
int lengthLeft = left.length;
int lengthRight = right.length;
while (lengthLeft > 0 && lengthRight > 0){
if (left[left.length - lengthLeft] < right[right.length - lengthRight]){
merged[merged.length -lengthLeft-lengthRight] = left[left.length - lengthLeft];
lengthLeft--;
}else{
merged[merged.length - lengthLeft-lengthRight] = right[right.length - lengthRight];
lengthRight--;
}
}
while (lengthLeft > 0){
merged[merged.length - lengthLeft] = left[left.length-lengthLeft];
lengthLeft--;
}
while (lengthRight > 0){
merged[merged.length - lengthRight] = right[right.length-lengthRight];
lengthRight--;
}
return merged;
}
static void mergeSort(int arr[],int p, int r) {
if(p<r) {
System.out.println("Pass "+k++);
int q = (p+r)/2;
mergeSort(arr,p,q);
mergeSort(arr,q+1,r);
//System.out.println(p+" "+q+" "+r);
merge(arr,p,q,r);
}
}
static void merge(int arr[],int p,int q,int r) {
int temp1[],temp2[];
//lower limit array
temp1 = new int[q-p+1];
//upper limit array
temp2 = new int[r-q];
for(int i=0 ; i< (q-p+1); i++){
temp1[i] = arr[p+i];
}
for(int j=0; j< (r-q); j++){
temp2[j] = arr[q+j+1];
}
int i = 0,j=0;
for(int k=p;k<=r;k++){
// This logic eliminates the so called sentinel card logic mentioned in Coreman
if(i!= temp1.length
&& (j==temp2.length || temp1[i] < temp2[j])
) {
arr[k] = temp1[i];
// System.out.println(temp1[i]);
i++;
}
else {
//System.out.println(temp2[j]);
arr[k] = temp2[j];
j++;
}
}
}
>
Merge Sort Using Sentinel
This codes works perfectly fine.
public void mergeSort(int a[], int low, int high) {
if (low < high) {
int mid = (low + high) / 2;
mergeSort(a, low, mid);
mergeSort(a, mid + 1, high);
merge(a, low, mid, high);
}
}
public void merge(int a[], int low, int mid, int high) {
int n1 = mid - low + 1;// length of an array a1
int n2 = high - mid; // length of an array a2
int a1[] = new int[n1 + 1];
int a2[] = new int[n2 + 1];
int lowRange = low;
for (int i = 0; i < n1; i++) {
a1[i] = a[lowRange];
lowRange++;
}
for (int j = 0; j < n2; j++) {
a2[j] = a[mid + j + 1];
}
a1[n1] = Integer.MAX_VALUE; // inserting sentinel at the end of array a1
a2[n2] = Integer.MAX_VALUE; // inserting sentinel at the end of array a2
int i = 0;
int j = 0;
int k = low;
for (k = low; k <= high; k++) {
if (a1[i] >= a2[j]) {
a[k] = a2[j];
j++;
} else {
a[k] = a1[i];
i++;
}
}
if (a2.length >= a1.length) {
for (int ab = k; ab < a2.length; ab++) {
a[k] = a2[ab];
k++;
}
} else if (a1.length >= a2.length) {
for (int ab = k; ab < a1.length; ab++) {
a[k] = a1[ab];
k++;
}
}
}
Here's another alternative:
public class MergeSort {
public static void merge(int[]a,int[] aux, int f, int m, int l) {
for (int k = f; k <= l; k++) {
aux[k] = a[k];
}
int i = f, j = m+1;
for (int k = f; k <= l; k++) {
if(i>m) a[k]=aux[j++];
else if (j>l) a[k]=aux[i++];
else if(aux[j] > aux[i]) a[k]=aux[j++];
else a[k]=aux[i++];
}
}
public static void sort(int[]a,int[] aux, int f, int l) {
if (l<=f) return;
int m = f + (l-f)/2;
sort(a, aux, f, m);
sort(a, aux, m+1, l);
merge(a, aux, f, m, l);
}
public static int[] sort(int[]a) {
int[] aux = new int[a.length];
sort(a, aux, 0, a.length-1);
return a;
}
}
Here is a simple merge sort algorithm in Java:
Good Tip: Always use int middle = low + (high-low)/2 instead of int middle = (low + high)/2.
public static int[] mergesort(int[] arr) {
int lowindex = 0;
int highindex = arr.length-1;
mergesort(arr, lowindex, highindex);
return arr;
}
private static void mergesort(int[] arr, int low, int high) {
if (low == high) {
return;
} else {
int midIndex = low + (high-low)/2;
mergesort(arr, low, midIndex);
mergesort(arr, midIndex + 1, high);
merge(arr, low, midIndex, high);
}
}
private static void merge(int[] arr, int low, int mid, int high) {
int[] left = new int[mid-low+2];
for (int i = low; i <= mid; i++) {
left[i-low] = arr[i];
}
left[mid-low+1] = Integer.MAX_VALUE;
int[] right = new int[high-mid+1];
for (int i = mid+1; i <= high; i++) {
right[i-mid-1] = arr[i];
}
right[high - mid] = Integer.MAX_VALUE;
int i = 0;
int j = 0;
for (int k = low; k <= high; k++) {
if (left[i] <= right[j]) {
arr[k] = left[i];
i++;
} else {
arr[k] = right[j];
j++;
}
}
}
package com.sortalgo;
import java.util.Arrays;
public class MyMSort {
private static void merge(int[] array, int[] result, int low, int mid, int high) {
int k =low, i=low; int j=mid+1;
while(i<=mid && j<=high) {
if(array[i]<= array[j]) {
result[k++]=array[i++];
}else {
result[k++]=array[j++];
}
}
while(i<=mid) {
result[k++]=array[i++];
}
while(j<=high) {
result[k++]=array[j++];
}
for(i=low;i<=high;i++) {
array[i]=result[i];
}
}
private static void mergeSort(int[] array, int[] result, int low, int high) {
if(high == low) {
return ;
}
int mid = (low + high)/2;
mergeSort(array,result, low, mid );
mergeSort(array,result, mid+1, high );
merge(array, result, low, mid, high);
}
public static void main(String[] args) {
int[] array = {8,4,3,12,25,6,13,10};
int[] result = new int[array.length];
mergeSort(array, result, 0, array.length-1 );
for(int i=0; i<=array.length-1;i++) {
System.out.println(array[i]);
}
}
}

Categories

Resources