Java 一次合并排序3个子数组
我正在制作一个程序来实现mergesort算法,但不是每次将它们分成2部分,而是每次将它们分成3部分,然后递归地进行mergesort排序。如果我把你搞糊涂了,它基本上是一个合并排序,但不是用2个部分合并排序,而是每次用3个部分合并排序,听起来很有趣吧?当然不是 以下是我对mergesort的实现: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
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