0

I have an assignment about modifying Cormen's merge sort algorithm into a 3 way merge. My instructor does not like outside book materials, so I am strictly abiding by cormen's algorithm. Now, I have tried to do that, but how ever it shows something like this

Exception in thread "main" java.lang.NegativeArraySizeException: -1
        at Algorithms.Mergemod.merge(Mergemod.java:10)
        at Algorithms.Mergemod.mergeSort(Mergemod.java:60)
        at Algorithms.Mergemod.mergeSort(Mergemod.java:58)
        at Algorithms.Mergemod.mergeSort(Mergemod.java:59)
        at Algorithms.Mergemod.mergeSort(Mergemod.java:58)
        at Algorithms.Mergemod.main(Mergemod.java:83)

I have tried the debugger and there in the mergeSort function I see r holds value sometimes 1, sometimes 3 and not 11. Here is my confusion why r would hold 1 or 3 and not 11. I have passed the last index of the array as r in the function.

My code:

package Algorithms;
import java.util.Scanner;
public class Mergemod {
    
    static void merge(int [] A, int p, int q, int t, int r ){
        int n1 = q-p+1;
        int n2 = t-q;
        int n3 = r-t;

        int [] L = new int[n1];
        int [] M = new int[n2];
        int [] R = new int[n3];

        //inserting values from A to L
        for (int i = 0; i < L.length; i++) {
            L[i] = A[p+i];
        }
        //inserting values from A to M
        for (int j = 0; j < M.length; j++) {
            M[j] = A[q+j+1];
        }
        //inserting values from A to R
        for (int k = 0; k < R.length; k++) {
            R[k] = A[t+k+1];
        }
        
        int i = 0 , j = 0, k = 0, l;
        //sorting and merging
        for (l = p; l <=r && i<n1 && j<n2 && k<n3; l++) {
            if(L[i]<=M[j] && L[i]<=R[k]){
                A[l] = L[i];
                i++;
            }
            else if(M[j]<=L[i] && M[j]<=R[k]){
                A[l] = M[j];
                j++;
            }
            else{
                A[l] = R[k];
                k++; 
            }   
        }
        while(i<n1){
            A[l++] = L[i++];
        }
        while(j<n2){
            A[l++] = M[j++];
        }
        while(k<n3){
            A[l++] = R[k++];
        }
    }
    static void mergeSort(int [] A, int p, int r){
        if(p<r)
        {   int q = (p+r)/3;
            int t = (q+1+r)/2;
            mergeSort(A, p, q);
            mergeSort(A, q+1, t);
            mergeSort(A, t+1, r);
            merge(A, p, q, t, r);
        }


    }
    public static void main(String[] args) {
        
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter the size of the array: ");
        int [] arr = new int [sc.nextInt()];
        System.out.println("Enter numbers : 11 5 20 3 4 8 0 15 2 13 1 6");
        for (int i = 0; i < arr.length; i++) {
            arr[i]= sc.nextInt();
        }
        System.out.println("Before merge sort");
        for (var x : arr) {
            System.out.print(x+" ");
        }
        
        int firstIndex = 0;
        int lastIndex = arr.length-1; 
        System.err.println(" ");
        System.out.println("After merge sort ");
        mergeSort(arr, firstIndex, lastIndex);
        for (var k : arr) {
            System.out.print(k+" ");
        }
        sc.close();
    }
}

I do not know if my logic is correct or not but if anybody would help me out that would mean so much. Also I am not very good in java, so sorry for if there is any readability issue. Thanks!

  • After the 3 way merge reaches the end of one of the runs, it needs to drop down to a 2 way merge until it reaches the end of another run, before it does a copy of the rest of the final remaining run. – rcgldr Mar 12 '21 at 19:23
  • @rcgldr could you please elaborate what you said? I did not understand fully. Sorry for this. – Khanzaadeh Mar 12 '21 at 20:42
  • @rcgldr I get the idea what you are suggesting but I am having a hard time implementing what you said me to do. would you be kind enough to share a code snippet? That would be a lot of help. Thank you so much for reaching out, means a lot <3 – Khanzaadeh Mar 12 '21 at 23:24
  • I am allowed to check indexes and not use sentinels. There was no particular restriction mentioned except that I should not other algorithms. – Khanzaadeh Mar 13 '21 at 05:03
  • @rcgldr also I’d like to know if my logic is correct or not like the way i am dividing the entire array into 3 sub arrays and then storing values from the array to sub arrays? I know I somehow messed up in the sorting and merging procedure. I’m too novice for such problems. – Khanzaadeh Mar 13 '21 at 05:07

2 Answers2

0

I'll update this answer as you make progress. Update your question as you make progress.

int q = p + (r+1-p)/3;   // split
int t = q + (r+2-p)/3;

In merge():

if (r-p) < 1, return
if (r-p) < 2, compare a[p] : a[r], swap if out order, return

3 way merge, 
 if the end of L[] is reached, L = M, M = R, i = j, j = k, break to 2 way merge
 if the end of M[] is reached, M = R, j = k, break to 2 way merge
 if the end of R[] is reached, break to 2 way merge
 
2 way merge L[] and M[] using i and j
 if the end of L[] is reached, L = M, i = j break to copy
 if the end of M[] is reached, break to copy

copy the rest of L[]
rcgldr
  • 27,407
  • 3
  • 36
  • 61
  • my function definition is void merge(). How do I return something? – Khanzaadeh Mar 21 '21 at 14:39
  • I've updated something will you check? I would like to know from you using a priority queue how does it affect my time complexity for this 3 way mergeSort algorithm. – Khanzaadeh Mar 21 '21 at 15:46
  • @Khanzaadeh - using minheap will increase time complexity. Let z = p+1-r, then time complexity to add and remove each element to|from the heap is O(log(z)) as opposed to O(1) for if|else|copy sequence. – rcgldr Mar 21 '21 at 16:38
0

instead of doing that, I tried my luck using a priority queue. Loaded three of the arrays into the min heap and then removed every item from the minheap to my array A.


        PriorityQueue<Integer> minHeap = new PriorityQueue<>();
        for (Integer x : L) {
            minHeap.add(x);
        }
        for (Integer v : M) {
            minHeap.add(v);
        }
        for (Integer g : R) {
            minHeap.add(g);
        }
        for (int i = p; i <=r; i++) {
            A[i]= minHeap.remove();
        }

Thank you so much for that modified split from you. Worked like a charm. @rcgldr