Java 一次合并排序3个子数组

Java 一次合并排序3个子数组,java,arrays,merge,divide-and-conquer,Java,Arrays,Merge,Divide And Conquer,我正在制作一个程序来实现mergesort算法,但不是每次将它们分成2部分,而是每次将它们分成3部分,然后递归地进行mergesort排序。如果我把你搞糊涂了,它基本上是一个合并排序,但不是用2个部分合并排序,而是每次用3个部分合并排序,听起来很有趣吧?当然不是 以下是我对mergesort的实现: public static void mergesort(int[] data) { int elements = data.length; int sizeLeft; in

我正在制作一个程序来实现mergesort算法,但不是每次将它们分成2部分,而是每次将它们分成3部分,然后递归地进行mergesort排序。如果我把你搞糊涂了,它基本上是一个合并排序,但不是用2个部分合并排序,而是每次用3个部分合并排序,听起来很有趣吧?当然不是

以下是我对mergesort的实现:

public static void mergesort(int[] data) {
    int elements = data.length;
    int sizeLeft;
    int sizeCenter;
    int sizeRight;

    if (elements > 2) {

        if (elements % 3 == 0) {
            sizeLeft = elements / 3;
            sizeCenter = elements / 3;
            sizeRight = elements / 3;
        } else if (elements % 3 == 1) {
            sizeLeft = (elements / 3) + 1;
            sizeCenter = elements / 3;
            sizeRight = elements / 3;
        } else { //if (elements % 3 == 2)
            sizeLeft = (elements / 3) + 1;
            sizeCenter = elements / 3;
            sizeRight = (elements / 3) + 1;
        }

        int[] left = makeArray(data, 0, sizeLeft);
        int[] center = makeArray(data, sizeLeft, sizeCenter);
        int[] right = makeArray(data, sizeLeft + sizeCenter, sizeRight);

        mergesort(left);
        mergesort(center);
        mergesort(right);

        merge(data, left, center, right);
    }
}
以下是合并方法的示例:

public static void merge(int[] data, int[] left, int[] center, int[] right) {
    int[] temp = new int[left.length + center.length + right.length];
    int copiedTotal = 0;
    int copiedLeft = 0;
    int copiedCenter = 0;
    int copiedRight = 0;

    while ((copiedLeft < left.length)
            && (copiedCenter < center.length)
            && (copiedRight < right.length)) {

        if ((left[copiedLeft] < center[copiedCenter])
                && (left[copiedLeft] < right[copiedRight])) {

            temp[copiedTotal++] = left[(copiedLeft++)];
        } else if ((center[copiedCenter] < left[copiedLeft])
                && (center[copiedCenter] < right[copiedRight])) {
            temp[copiedTotal++] = center[copiedCenter++];
        } else {
            temp[copiedTotal++] = right[copiedRight++];
        }
    }

    while ((copiedLeft < left.length) && (copiedCenter < center.length)) {
        if (left[copiedLeft] < center[copiedCenter]) {
            temp[copiedTotal++] = left[copiedLeft++];
        } else{
            temp[copiedTotal++] = center[copiedCenter++];
        }
    }

    while ((copiedLeft < left.length) && (copiedRight < right.length)) {
        if (left[copiedLeft] < right[copiedRight]) {
            temp[copiedTotal++] = left[copiedLeft++];
        } else{
            temp[copiedTotal++] = right[copiedRight++];
        }
    }

    while ((copiedCenter < center.length) && (copiedRight < right.length)) {
        if (center[copiedCenter] < right[copiedRight]) {
            temp[copiedTotal++] = center[copiedCenter++];
        } else{
            temp[copiedTotal++] = right[copiedRight++];
        }
    }

    while (copiedLeft < left.length) {
        temp[copiedTotal++] = left[copiedLeft++];
    }

    while (copiedCenter < center.length) {
        temp[copiedTotal++] = center[copiedCenter++];
    }

    while (copiedRight < right.length) {
        temp[copiedTotal++] = right[copiedRight++];
    }
    System.arraycopy(temp, 0, data, 0, left.length + center.length + right.length);
//        for (int i = 0; i < data.length; i++) {
//            if ((copiedRight >= right.length) && (copiedCenter >= center.length)) {
//                data[i] = left[copiedLeft];    // take from left
//                copiedLeft++;
//            } else if ((copiedRight >= right.length) && (copiedLeft >= left.length)) {
//                data[i] = center[copiedCenter];    // take from left
//                copiedCenter++;
//            } else if ((copiedCenter >= center.length) && (copiedLeft >= left.length)) {
//                data[i] = right[copiedRight];    // take from left
//                copiedRight++;
//            } else if ((copiedLeft < left.length
//                    && left[copiedLeft] <= right[copiedRight])
//                    && left[copiedLeft] <= center[copiedCenter]) {
//
//                data[i] = left[copiedLeft];    // take from left
//                copiedLeft++;
//
//            } else if ((copiedRight >= right.length) && (copiedLeft >= left.length)
//                    || (copiedCenter < center.length
//                    && center[copiedCenter] <= right[copiedRight])
//                    && center[copiedCenter] <= left[copiedLeft]) {
//
//                data[i] = center[copiedCenter];    // take from center
//                copiedCenter++;
//            } else {
//                data[i] = right[copiedRight];
//                copiedRight++;// take from center
//            }
//
//        }
    }
}
公共静态无效合并(int[]数据,int[]左,int[]中心,int[]右){
int[]temp=newint[left.length+center.length+right.length];
int copiedTotal=0;
int copiedLeft=0;
int copiedCenter=0;
int copiedRight=0;
while((copiedLeft=right.length)和&(copiedCenter>=center.length)){
//数据[i]=左[copiedLeft];//从左取
//copiedLeft++;
//}else如果((copiedRight>=right.length)和&(copiedLeft>=left.length)){
//数据[i]=中心[copiedCenter];//从左边开始
//copiedCenter++;
//}else如果((copiedCenter>=center.length)和&(copiedLeft>=left.length)){
//数据[i]=右[copiedRight];//从左取
//copiedRight++;
//}else如果((copiedLeft//&¢er[copiedCenter]问题似乎在于,当你有一个2元素数组时,你不需要对它做任何事情。你应该对它进行排序。如果你以[6,5,4,3,2,1]为例,在递归的第二步,你有[2,1];[4,3]和[6,5]您可以这样合并它们。如果您先对它们进行排序,您将获得正确的顺序。为了在合并函数中对它们进行排序,您应该添加:

if ((elements==2)&&(data[1]<data[0])){
 int aux = data[1];
 data[1] = data[0];
 data[0] = aux;
}

更新2
您可以重构我显示的代码,使其看起来更漂亮。基本思想是,您可以在Java中使用空数组,并且您的合并函数可以正确地处理它。希望我能更清楚地说明我的观点。

您是否使用调试器完成了此操作?@LouisWasserman我使用调试器完成了此操作,并且该程序似乎只接受了pai这就是为什么我这么困惑的原因。另外,熟悉mergesort算法的Vipar人员会发现,这不仅仅是一堵巨大的代码墙,而是一个用于3个子数组而不是2个子数组的修改。由于我花了太多时间搜索和查看调试器,并重新编写代码,我感到非常困惑很明显,这里没有寻找简单易用的代码,我的问题很清楚,再读一遍,我只是想了解一些信息。这是一个很好的例子,说明了与算法的big-O相关的常数是如何使某些技术效率低下的。+1我想知道
if(elements>2){
但我没有把它放在一起。是的,我想到了,但问题是,它似乎不完全是一个合并排序,而是一个由2部分组成的合并排序,由3部分组成的合并排序,我只是不确定这是否符合3部分合并排序的条件。如果你想要一个纯合并排序,你可以尝试以下方法:当elements为2时,只需将center=[]、left=[data[0]]和right=[data[1]]设为。我将用代码更新答案。关于您的更新,您是在暗示我应该有第二个mergesort,它是常规的mergesort(拆分为2)使用这个mergesort对两个左右数组进行排序?只是我不能在java中有一个空数组(中间的一个),即使我不能,它也会在我创建的mergesort中产生问题吗?你可以在java中有一个空数组,通过阅读你的合并函数,它应该工作得很好(假设空数组的长度为0)。我想说的是,您可以使用空数组调用合并排序函数。我将对答案进行第二次更新,以使其更清楚。
if (elements==2){
 int[] center = [];
 int[] left = makeArray(data,0,1);
 int[] right =makeArray(data,1,1);

 mergesort(left); //you can call these methods or not, on a empty or 1 element array they dont have an effect
 mergesort(center);
 mergesort(right);

 merge(data, left, center, right); //it should work well when center is an empty array