【发布时间】:2012-05-27 07:54:15
【问题描述】:
我正在制作一个实现归并排序算法的程序,但不是每次将它们分成两部分,而是每次将它们分成三部分并递归地对它们进行归并排序。万一我把你弄糊涂了,它基本上是一个归并排序,但不是用 2 个部分归并排序,而是每次归并排序 3,听起来很有趣吧?好吧,绝对不是。
这是我的合并排序实现:
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
// }
//
// }
}
}
在合并方法内的 cmets 中,我尝试制作另一种合并方法,但结果并不好,事情变得更加复杂,但我把它留在那里以供参考。
问题是这根本不起作用,例如,如果我有:
输入:6 5 4 3 2 1
那我就有了:
输出:[2, 1, 4, 3, 6, 5]
老实说,我为此非常努力,连续 2 天,我发现只有两个人听说过这种合并排序,在谷歌搜索数小时后,我在这里只发现了一个类似的问题(这太复杂了,无法理解)以及 wiki 答案中的另一个线程从未得到回答。
任何帮助都将不胜感激,当然我并不是在寻求直接的解决方案,因为我正在努力学习,但是提示和提示以及我做错了什么会对我有很大帮助。
提前致谢。
【问题讨论】:
-
你用调试器解决过这个问题吗?
-
-
另外 Vipar 熟悉合并排序算法的人会看到,这不仅仅是一些大代码墙,而是用于 3 个子数组而不是 2 个子数组的更改,因为我花了这么多时间搜索和查看调试器并重新编写代码我显然不是在这里寻找简陋和现成的代码,我的问题很清楚,再次阅读我只是在寻求提示
-
这是一个很好的例子,说明与算法的大 O 相关的常数如何使某些技术效率低下。
标签: java arrays merge divide-and-conquer