MergeSort problems parameters - java

import java.lang.reflect.Array;
public class Sorting {
public static void mergeSort(CompareInt[] arr) {
for(int i=0;i<=arr.length-1;i++){
System.out.println("Initial Arr element:"+arr[i].val);
}
CompareInt[] arrAux;
arrAux = new CompareInt[arr.length];
mergeS(arr,0,arr.length-1,arrAux);
}
public static void mergeS(CompareInt[] arr,int startI,int endI,CompareInt[] arrAux){
//System.out.println("StartIndex:"+startI+" EndIndex:"+endI);
if(endI-startI<=0)
return;
int mid = (startI+endI)/2;
// System.out.println("Midpoint value:"+mid);
mergeS(arr,startI,mid);
mergeS(arr,mid+1,endI);
// System.out.println("Inside mergeS");
// System.out.println("StartIndex:"+startI+" EndIndex:"+endI+" Midpoint value:"+mid);
// System.out.println("Arr length:"+arr.length);
arrAux = merge(arr,mid);
for(int i=0;i<=arr.length-1;i++){
arr[i]=arrAux[i];
System.out.println("Arr element:"+arr[i].val);
}
}
public static CompareInt[] merge(CompareInt[] arr,int midpoint){
int i=0,j=0,k=0;
int n1 = arr.length-midpoint;
int n2 = arr.length-n1;
//System.out.println("Midpoint value inside merge:"+midpoint);
//System.out.println("N1:"+n1+" N2:"+n2);
CompareInt[] L;
CompareInt[] R;
CompareInt[] resA;
L = new CompareInt[n1];
R = new CompareInt[n2];
resA = new CompareInt[n1+n2];
for(i=0;i<n1;i++){
L[i]=arr[i];
// System.out.println("Inside Left loop"+i);
// System.out.println(L[i].val);
}
for(j=0;j<n2;j++){
R[j]=arr[midpoint+j+1];
// System.out.println("Inside Right loop "+j);
// System.out.println(R[j].val);
}
i=0;
j=0;
k=0;
while(i<n1 && j<n2){
if(L[i].compareTo(R[j])<=0){
resA[k]=L[i];
// System.out.println(resA[i].val);
i++;
}
else{
resA[k]=R[j];
// System.out.println(resA[j].val);
j++;
}
k++;
}
while(i<n1){
resA[k]=L[i];
//System.out.println(resA[k].val);
i++;
k++;
}
while(j<n2){
resA[k]=R[j];
//System.out.println(resA[k].val);
j++;
k++;
}
return resA;
}
}
I am getting actual and formal argument lists differ in length at line mereS(..)
How do I solve this error and is there any way to run with different number of arguments in actual and formal parameters.
This is how Pseudo code is given ..
Modifications in pseudo code:
if (hi - lo <= 0)", not "if (hi - lo <= 1)".
aux <- merge(A[lo:mid], A[mid+1:hi])

This code will sort out your problem :
public static void main(String[] args) {
int arr[] = {12, 11, 13, 5, 6, 7};
System.out.println("\nSorted array");
for(int i=0;i<=arr.length-1;i++){
System.out.println("Initial Arr element:"+arr[i]);
}
mergeS(arr, 0, arr.length-1);
System.out.println("\nSorted array");
for(int i=0;i<=arr.length-1;i++){
System.out.println("Sorted Arr element:"+arr[i]);
}
}
public static void mergeS(int[] arr,int startI,int endI){
//System.out.println("StartIndex:"+startI+" EndIndex:"+endI)
if (startI< endI)
{
// Find the middle point
int m = (startI+endI)/2;
// Sort first and second halves
mergeS(arr,startI, m);
mergeS(arr , m+1, endI);
// Merge the sorted halves
merge(arr, startI,m, endI);
}
}
public static void merge(int arr[], int startI, int midpoint, int endI){
// Find sizes of two subarrays to be merged
int n1 = midpoint - startI + 1;
int n2 = endI - midpoint;
/* Create temp arrays */
int L[] = new int [n1];
int R[] = new int [n2];
/*Copy data to temp arrays*/
for (int i=0; i<n1; ++i)
L[i] = arr[startI + i];
for (int j=0; j<n2; ++j)
R[j] = arr[midpoint + 1+ j];
/* Merge the temp arrays */
// Initial indexes of first and second subarrays
int i = 0, j = 0;
// Initial index of merged subarry array
int k = startI;
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
i++;
}
else
{
arr[k] = R[j];
j++;
}
k++;
}
/* Copy remaining elements of L[] if any */
while (i < n1)
{
arr[k] = L[i];
i++;
k++;
}
/* Copy remaining elements of R[] if any */
while (j < n2)
{
arr[k] = R[j];
j++;
k++;
}
}

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];
}

Divide and Conquer Algorithm (MergeSort Algo) calculating number of inversions

I am trying to solve the problem of calculating the number of inversions where the problem is:
`An inversion of a sequence 𝑎0, 𝑎1, . . . , 𝑎𝑛−1 is a pair of indices 0 ≤ 𝑖 < 𝑗 < 𝑛 such
that 𝑎𝑖 > 𝑎𝑗. The number of inversions of a sequence in some sense measures how
close the sequence is to being sorted. For example, a sorted (in non-descending
order) the sequence contains no inversions at all, while in a sequence sorted in descending
order any two elements constitute an inversion (for a total of 𝑛(𝑛 − 1)/2
inversions).
Sample Input is:
6
9 8 7 3 2 1
The output will be:
15
`
Now for this, I am trying to merge the sort algorithm and the idea is whenever I will see nextNo. greater than prevNo. I will add count which is 0 initially.
This is the Merge algorithm:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class MergeSort {
static void Merge(int arr[],int l,int m, int r){
int n1 = m-l+1;
int n2 = r-m;
int L[] = new int[n1];
int R[] = new int[n2];
for(int i=0;i<n1;i++)
L[i] = arr[i+l];
for(int i=0;i<n2;i++)
R[i] = arr[m+1+i];
int i=0,j=0;
int k=l;
while(i<n1&&j<n2){
if(L[i]<R[j]){
arr[k]=L[i];
i++;
}
else{
arr[k]=R[j];
j++;
}
k++;
}
while(i<n1){
arr[k] =L[i];
i++;
k++;
}
while(j<n2){
arr[k] =R[j];
j++;
k++;
}
}
static void MergeSortBasic(int arr[],int l,int r) {
if(l<r){
int m = (l+r)/2;
MergeSortBasic(arr,l,m);
MergeSortBasic(arr,m+1,r);
Merge(arr,l,m,r);
}
}
public static void main(String[] args) {
QuickSortAlgo.FastScanner scanner = new QuickSortAlgo.FastScanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
MergeSortBasic(a,0,n-1);
for (int i = 0; i < n; i++) {
System.out.print(a[i] + " ");
}
}
static class FastScanner {
BufferedReader br;
StringTokenizer st;
FastScanner(InputStream stream) {
try {
br = new BufferedReader(new InputStreamReader(stream));
} catch (Exception e) {
e.printStackTrace();
}
}
String next() {
while (st == null || !st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}
This I understand but here is the solution to this problem that I came across which I could not understand. Can please someone help me in understanding the solution of this algorithm especially the midpoint/ave part.
Solution:
import java.util.*;
public class Inversions {
private static long merge(int[] a, int[] b, int left, int ave, int right) {
int i = left, j = ave, k = left;
long inv_count = 0;
while (i <= ave - 1 && j <= right) {
if (a[i] <= a[j]) {
b[k] = a[i];
i++;
} else {
b[k] = a[j];
inv_count += ave - i;
j++;
}
k++;
}
while (i <= ave - 1) {
b[k] = a[i];
i++;
k++;
}
while (j <= right) {
b[k] = a[j];
j++;
k++;
}
for (i = left; i <= right; i++) {
a[i] = b[i];
}
return inv_count;
}
private static long getNumberOfInversions(int[] a, int[] b, int left, int right) {
long inv_count = 0;
if (right <= left) {
return inv_count;
}
int ave = left + (right - left) / 2;
inv_count += getNumberOfInversions(a, b, left, ave);
inv_count += getNumberOfInversions(a, b, ave + 1, right);
inv_count += merge(a, b, left, ave + 1, right);
return inv_count;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextInt();
}
int[] b = new int[n];
System.out.println(getNumberOfInversions(a, b, 0, a.length - 1));
}
}
My question is Why do we have
inv_count += ave - i;
Instead of simply:
inv_count++;
Like what is the difference between these two programs?? How is this ave variable working? Also, any idea how can I learn this effectively in the future?
why: inv_count += ave - i;
The two sub-arrays being merged are already sorted from prior recursions (or an end case where sub-array size is 1 element). Each time an element from the right sub-array is found to be less than the current element in the left sub-array (a[j] < a[i]), the number of elements remaining in the left sub-array (ave - i) is added to the inversion count, because a[j] is less than all of the elements from a[i] through a[ave-1].

I am trying to count the number of comparison's in a heap sort and a quick sort

The purpose of this project is to create two arrays of random numbers and run a quick sort and heap sort of them. Keep track of the number of comparison's and then compare them. Both sorts work, but my heap sort wont keep track of the comparison's. it just says 0. My quick sort works and puts the comparisons in an array. How do i fix this?
package sorting;
import java.util.Arrays;
//import java.util.Random;
import java.util.*;
public class project2
{
static int [] heap_sort_comparison = new int[21];
static int [] quick_sort_comparison = new int[21];
static int [] array1 = new int [20];
static int [] array2 = new int [20];
static int compares = 0;
static int heap_compares = 0;
private static void quickSort(int[] array1, int l, int h) {
if(l < h ) {
compares++;
int position = partition(array1, l, h);
quickSort(array1,l, position -1);
quickSort(array1, position +1, h);
}
}
private static int partition(int[] array1, int i, int j) {
int pivot = array1[j] -1;
int small = i -1;
for(int k = i; k < j; k++) {
if(array1[k] <= pivot) {
compares++;
small++;
swap(array1, k, small);
}
}
swap(array1, j, small + 1);
//System.out.println("Pivot = " + array1[small + 1]);
print_quick_sort(array1);
return small + 1;
}
public static void swap(int[] array1, int a, int b) {
int temp;
temp = array1[a];
array1[a] = array1[b];
array1[b] = temp;
}
public static void print_quick_sort(int[] array1) {
for(int i = 0; i < array1.length; i++) {
System.out.print(array1[i] + " ");
}
System.out.println();
}
//HEAP SORT
public void build(int array2[]) {
int length = array2.length;
for(int i = length/2-2; i >=0; i--) {
bubble_down(array2, i, array2.length-1);
heap_compares++;
}
for(int i = length-1; i>= 0; i--) {
swap2(array2, 0,i);
bubble_down(array2,i,0);
heap_compares++;
}
}
void bubble_down(int[] array2, int parent, int size) {
int left = parent*2+1;
int right = 2*parent+2;
int largest = 0;
if(left <= size && array2[left] > array2[largest]) {
largest = left;
heap_compares++;
}
if(right <= size && array2[right] > array2[largest]) {
largest = right;
heap_compares++;
}
if(largest != parent) {
swap2(array2,parent, largest);
bubble_down(array2,largest,size);
heap_compares++;
}
}
public static void swap2(int[] array2, int a, int b) {
int temp = array2[a];
array2[a] = array2[b];
array2[b] = temp;
}
public static void print_heap_sort(int[] array2) {
for(int i = 0; i < array2.length; i++) {
System.out.print(array2[i] + " ");
}
System.out.println();
}
public static void main(String[] args) {
for(int x = 0; x < 20; x++) {
for(int y = 0; y < 20; y++) {
for(int i = 0; i < array1.length; i++) {
array1[i] = array2[i]= (int)(Math.random()*20 + 0);
}
System.out.println("Numbers Generated in Array 1: " + Arrays.toString(array1));
System.out.println("");
System.out.println("Numbers Generated in Array 2: " + Arrays.toString(array2));
System.out.println("");
//quickSort
print_quick_sort(array1);
quickSort(array1, 0, array1.length -1);
System.out.println("The number of comparisons in quick sort: "+ compares);
System.out.println("=============================");
quick_sort_comparison[x] = compares;
compares = 0;
System.out.println("Array of quick sort comparison's: ");
System.out.println(Arrays.toString(quick_sort_comparison));
System.out.println("=============================");
//Heap Sort
System.out.println("Before Heap Sort: ");
System.out.println(Arrays.toString(array2));
heap_sort_comparison[y] = heap_compares;
heap_compares = 0;
HeapSort ob = new HeapSort();
ob.sort(array2);
System.out.println("Sorted array is (heap Sort): ");
print_heap_sort(array2);
System.out.println("=============================");
System.out.println("Array of heap sort comparison's: " + heap_compares);
System.out.println(Arrays.toString(heap_sort_comparison));
}
}
}
}
You do not even call the HeapSort method that you've built.
look here...
HeapSort ob = new HeapSort();
ob.sort(array2);
I think you are trying to use a built in sorting method from HeapSort class, So how do you think the counter heap_compares will increase!

Java Integer Array Rotation (Left)

I have a simple rotation function which takes an array and a number to rotate the numbers left
e.g. [1,2,3,4,5] & 2 - output: [3,4,5,1,2].
I want to know the most efficient way of completing this function, whether it would be to convert the int array into a string a splice it or whether to copy the array or to convert to an List<Integer>.
If anyone wants additional information please ask!
my solution at the moment:
static int[] rotLeft(int[] a, int d) {
int lengthOfArray = a.length;
int[] temp = new int[lengthOfArray];
for(int i = 0; i < lengthOfArray; i++){
int newLocation = (i + (lengthOfArray - d)) % lengthOfArray;
temp[newLocation] = a[i];
}
return temp;
}
Simple way to do it with O(n) complexity is as below along with handling of valid shifts int[] arr: is an int array, n=length of an array, d=how many shifts required.
public int[] leftRotate(int[] arr, int n, int d) {
int rot = 0;
int[] marr = new int[n];
if (d < 0 || d == 0 || d>n) {
return arr;
}
else {
for (int i = 0; i < n; i++) {
if (i < n - d) {
marr[i] = arr[i + d];
} else {
marr[i] = arr[rot];
rot++;
}
}
return marr;
}
}
public void GetArray(int[] arr, int n, int d) {
int[] arr1 = leftRotate(arr, n, d);
for (int j : arr1) {
System.out.println(j);
}
}
public static void main(String args[]) {
int[] arr = { 1,2,3,4,5 };
int n = arr.length;
Test2 obj = new Test2();
obj.GetArray(arr, n, 2);
}
Why don't you try this one
void Rotate(int arr[], int d, int n)
{
for (int i = 0; i < d; i++)
leftRotatebyOne(arr, n);
}
void leftRotatebyOne(int arr[], int n)
{
int i, temp;
temp = arr[0];
for (i = 0; i < n - 1; i++)
arr[i] = arr[i + 1];
arr[i] = temp;
}
and to call this invoke method like below
int arr[] = { 1, 2, 3, 4, 5 };
Rotate(arr, 2, 5);

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