找不到将 cormen 的 mergeSort 算法修改为 3 路合并的方法

问题描述

我有一个关于将 Cormen 的合并排序算法修改为 3 路合并的作业。我的老师不喜欢书外的材料,所以我严格遵守 cormen 算法。现在,我已经尝试这样做了,但它如何显示这样的东西

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)

我已经尝试过调试器,在 mergeSort 函数中,我看到 r 的值有时为 1,有时为 3 而不是 11。这是我的困惑,为什么 r 会保留 1 或 3 而不是 11。我已经通过了最后一个索引数组作为函数中的 r。

我的代码

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 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,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();
    }
}

我不知道我的逻辑是否正确,但如果有人会帮助我,那将意义重大。另外我在java方面不是很好,如果有任何可读性问题,很抱歉。 谢谢!

解决方法

随着您的进步,我会更新此答案。随着您的进步,更新您的问题。

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

在合并()中:

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,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,i = j break to copy
 if the end of M[] is reached,break to copy

copy the rest of L[]
,

我没有这样做,而是使用优先级队列来试试运气。将三个数组加载到最小堆中,然后将最小堆中的每个项目都移到我的数组 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();
        }

非常感谢您修改后的拆分。像魅力一样工作。 @rcgldr