Java 三向合并排序问题排序不正确

Java 三向合并排序问题排序不正确,java,mergesort,Java,Mergesort,我一直在研究这个基于我的普通合并排序代码的三向合并排序算法;但是,它没有正确排序,因此我相信我的代码中可能有一个小错误。需要帮忙吗?我已经研究了3个小时的代码,试图找到问题,但事实证明这很困难 public class TriMergeSort { void merge(int arr[], int low, int mid1, int mid2, int high) { int sizeA = mid1 - low + 1; int sizeB =

我一直在研究这个基于我的普通合并排序代码的三向合并排序算法;但是,它没有正确排序,因此我相信我的代码中可能有一个小错误。需要帮忙吗?我已经研究了3个小时的代码,试图找到问题,但事实证明这很困难

public class TriMergeSort {

    void merge(int arr[], int low, int mid1, int mid2, int high) { 
        int sizeA = mid1 - low + 1; 
        int sizeB =  mid2 - mid1;
        int sizeC = high - mid2;

        int A[] = new int[sizeA]; 
        int B[] = new int[sizeB]; 
        int C[] = new int[sizeC];

        for (int i = 0; i < sizeA; i++) 
            A[i] = arr[low + i]; 
        for (int j = 0; j < sizeB; j++) 
            B[j] = arr[mid1 + j + 1]; 
        for (int x = 0; x < sizeC; x++) 
            C[x] = arr[mid2 + x + 1];

        int i = 0, j = 0, x = 0; 
        int k = low; 
        
        while (i < sizeA && j < sizeB && x < sizeC) {
            
            if (A[i] < B[j] && A[i] < C[x]) { 
                arr[k] = A[i]; 
                i++; 
            } else
            if (A[i] >= B[j] && B[j] < C[x]) { 
                arr[k] = B[j]; 
                j++; 
            } else
            if (A[i] > C[x] && B[j] >= C[x]) { 
                arr[k] = C[x]; 
                x++; 
            } 
            k++; 
        } 

        while (i < sizeA) { 
            arr[k] = A[i]; 
            i++; 
            k++; 
        } 

        while (j < sizeB) { 
            arr[k] = B[j]; 
            j++; 
            k++; 
        } 
        
        while (x < sizeC) { 
            arr[k] = C[x]; 
            x++; 
            k++; 
        }
    } 

    void sort(int arr[], int low, int high) { 
        
        if (low < high) {  
            int mid1 = low + ((high - low) / 3); 
            int mid2 = low + 2 * ((high - low) / 3) + 1;

            sort(arr, low, mid1); 
            sort(arr, mid1 + 1, mid2); 
            sort(arr, mid2 + 1, high);

            merge(arr, low, mid1, mid2, high); 
        } 
    } 

    static void print(int arr[]) { 
        int n = arr.length; 
        for (int i = 0; i < n; ++i) 
            System.out.print(arr[i] + " "); 
        System.out.println(); 
    } 

    public static void main(String args[]) { 
        int arr[] = { 15, 2, 6, 7, 55, 0, 28, 41, 12 }; 

        TriMergeSort test = new TriMergeSort(); 
        test.sort(arr, 0, arr.length - 1); 

        print(arr); 
    }
} 
公共类TriMergeSort{
无效合并(int arr[],int low,int mid1,int mid2,int high){
int sizeA=mid1-低+1;
int sizeB=mid2-mid1;
int sizeC=高-中2;
int A[]=新的int[sizeA];
int B[]=新int[sizeB];
int C[]=新的int[sizeC];
对于(int i=0;i=B[j]&B[j]C[x]&&B[j]>=C[x]){
arr[k]=C[x];
x++;
} 
k++;
} 
而(i
问题中的代码运行良好。您没有发布有问题的3向合并代码

请注意,不应将
high
作为索引传递给要排序的切片中的最后一项,而应将第一个元素的索引传递给切片之外的元素。这使得代码更简单,不会产生混淆和容易出错的调整

以下是修改后的版本:

公共类合并排序{
无效合并(int arr[],int low,int mid,int high){
int sizeA=中-低;
int sizeB=高-中;
int A[]=新的int[sizeA];
int B[]=新int[sizeB];
对于(int i=0;i
要将其转换为3路合并版本,
sort3
必须遵循以下步骤:

  • 将范围分成3个部分,而不是2个。第一个部分从
    low
    mid1=low+(high-low)/3
    排除,第二个从
    mid1
    mid2=low+(high-low)*2/3排除,第三个从
    mid2
    high
    排除
  • 对3个子切片中的每一个子切片进行递归排序
  • 呼叫
    merge3(arr、低、中1、中2、高)
    • 复制3个子切片
    • 为运行3个切片的3个索引值编写一个循环,直到其中一个已耗尽
    • 为剩余的2个切片(A和B)或(B和C)或(A和C)写入3个循环
    • 写3个循环以从剩余的片A、B或C复制剩余的元素
EDIT:您的
TriMergeSort
类中的
merge
函数缺少3个循环,当3个初始切片中的一个用完时,这些循环将合并2个切片。这解释了数组未正确排序的原因。在3路合并循环之后,您应该有:

    while (i < sizeA && j < sizeB) {
        ...
    }
    while (i < sizeA && x < sizeC) {
        ...
    }
    while (j < sizeB && x < sizeC) {
        ...
    }
甚至更进一步:

    while (low < high) {
        arr[low++] = (i < sizeA && (j >= sizeB || A[i] <= B[j])) ?
            ((k >= sizeC || A[i] <= C[k]) ? A[i++] : C[k++]) :
            (j < sizeB && (k >= sizeC || B[j] <= C[k])) ? B[j++] : C[k++];
    } 
while(低<高){

arr[low++]=(i=sizeB||A[i]=sizeC|A[i]=sizeC|B[j]使用调试器是一项重要技能,这是一个学习调试器的好机会。您没有发布不起作用的3向合并排序代码。编辑此帖子以显示我的3向合并排序…我的好友,请遵循java命名约定。数组名称也应以小写开头。非常感谢您提供的提示!我将帖子编辑为显示我的3路合并排序算法,因为我无意中发布了常规合并排序。
    while (low < high) {
        arr[low++] = (i < sizeA && (j >= sizeB || A[i] <= B[j])) ?
            ((k >= sizeC || A[i] <= C[k]) ? A[i++] : C[k++]) :
            (j < sizeB && (k >= sizeC || B[j] <= C[k])) ? B[j++] : C[k++];
    }