我编写了一些代码,将两个已排序的数组合并为一个已排序的数组。我纯粹是出于学习目的而这样做。我编写了自己的代码(没有查看它是如何完成的)并且遇到了一个奇怪的错误。我的代码大约在7/10的时间内工作,也就是说它将两个已排序的数组正确地推送到一个已排序的数组中(正常运行的7/10倍)。如果它没有正确排序,它总是朝向数组末尾的数字不正确。
这是一个不正确的示例输出(使用随机数填充到数组):[3, 16, 19, 24, 27, 33, 35, 41, 52, 55, 59, 67, 74, 77, 78, 79, 84, 87, 89, 91, 91, 92, 87, 92]
如您所见,错误(87)处于错误的位置。
以下是另一个示例:[0, 4, 7, 8, 10, 11, 15, 16, 24, 25, 31, 32, 38, 54, 58, 62, 63, 66, 67, 70, 75, 80, 62, 80]
另一个:[12, 14, 15, 25, 32, 34, 37, 42, 46, 48, 53, 54, 55, 58, 59, 60, 65, 66, 69, 70, 72, 79, 70, 79]
另一个:[4, 25, 25, 27, 30, 42, 42, 43, 49, 49, 58, 62, 63, 63, 64, 64, 68, 69, 74, 63, 64, 64, 69, 74]
我只是继续运行它,大约3/10时我得到一个未分类的输出。任何人都可以告诉我我的代码的哪一部分导致了这个问题?谢谢!
public static int[] mergeSortedLists(int[] arr1, int[] arr2)
{
int[] sortedArr = new int[arr1.length + arr2.length];
int n = 0, m = 0, independentCounter = 0;
while (n < arr1.length || m < arr2.length)
{
if (n != arr1.length && m != arr2.length)
{
if (arr1[n] < arr2[m])
{
sortedArr[independentCounter] = arr1[n++];
}
else
{
sortedArr[independentCounter] = arr2[m++];
}
}
else if (n == arr1.length)
{
copy(m, independentCounter, arr2, sortedArr);
break;
}
else if (m == arr2.length)
{
copy(n, independentCounter, arr2, sortedArr);
break;
}
independentCounter++;
}
return sortedArr;
}
public static void copy(int copyFromUnsortedIndex, int copyToSortedIndex, int[] unsortedArr, int[] sortedArr)
{
while (copyToSortedIndex < sortedArr.length && copyFromUnsortedIndex < unsortedArr.length)
{
sortedArr[copyToSortedIndex++] = unsortedArr[copyFromUnsortedIndex++];
}
}
答案 0 :(得分:3)
在copy()
两次调用中,您都指定了arr2
:
else if (n == arr1.length)
{
copy(m, independentCounter, arr2, sortedArr);
break;
}
else if (m == arr2.length)
{
copy(n, independentCounter, arr2, sortedArr);
break;
}
对于arr1
用作源索引的情况,您的意思是n
:
else if (m == arr2.length)
{
copy(n, independentCounter, arr1, sortedArr); // <- arr1
break;
}
这只会影响数组末尾数字的原因是这些情况不会发生,直到其中一个输入被完全消耗,这通常发生在最后。当arr2
短于arr1
时,您实际上是将错误数组的位复制到最后。
答案 1 :(得分:1)
我不知道答案,@ JasonC已经解决了一个重大问题。无论如何,这应该有助于你和那些试图解决它的人。它是一个完全可以工作的类,有一个演示输入,一个测试(main
)函数和一堆调试输出:
(我看到的唯一明显的问题是结果数组中的最后一项实际上是重复的,因为真正假定为最终的项目永远不会放在结果数组中。)
import java.util.Arrays;
/**
<P>{@code java SortTwoArrays}</P>
**/
public class SortTwoArrays {
public static final void main(String[] ignored) {
test(new int[]{1, 2, 3, 10, 11, 12, 99, 100, 120, 10000},
new int[]{35, 36, 37, 49, 51, 59, 1000, 2000, 2001, 9999});
}
private static final void test(int[] ints_a, int[] ints_b) {
System.out.println("A: " + Arrays.toString(ints_a));
System.out.println("B: " + Arrays.toString(ints_b));
System.out.println("Merged: " + Arrays.toString(mergeSortedLists(ints_a, ints_b)));
System.out.println();
}
public static int[] mergeSortedLists(int[] arr1, int[] arr2) {
int[] sortedArr = new int[arr1.length + arr2.length];
int n = 0, m = 0, independentCounter = 0;
while (n < arr1.length || m < arr2.length) {
if (n != arr1.length && m != arr2.length) {
if (arr1[n] < arr2[m]) {
sortedArr[independentCounter] = arr1[n++];
System.out.println("1. " + Arrays.toString(sortedArr));
} else {
sortedArr[independentCounter] = arr2[m++];
System.out.println("2. " + Arrays.toString(sortedArr));
}
} else if (n == arr1.length) {
copy(m, independentCounter, arr2, sortedArr);
System.out.println("3. " + Arrays.toString(sortedArr));
break;
} else if (m == arr2.length) {
copy(n, independentCounter, arr2, sortedArr);
System.out.println("4. " + Arrays.toString(sortedArr));
break;
}
independentCounter++;
}
return sortedArr;
}
public static void copy(int copyFromUnsortedIndex, int copyToSortedIndex, int[] unsortedArr, int[] sortedArr) {
while (copyToSortedIndex < sortedArr.length && copyFromUnsortedIndex < unsortedArr.length) {
sortedArr[copyToSortedIndex++] = unsortedArr[copyFromUnsortedIndex++];
System.out.println("5. Copied sortedArr[" + (copyToSortedIndex - 1) + "] (" + sortedArr[(copyToSortedIndex - 1)] + ") --> unsortedArr[" + (copyFromUnsortedIndex - 1) + "] (" + unsortedArr[(copyFromUnsortedIndex - 1)] + ")");
}
}
}
输出:
[C:\java_code\]java SortTwoArrays
A: [1, 2, 3, 10, 11, 12, 99, 100, 120, 10000]
B: [35, 36, 37, 49, 51, 59, 1000, 2000, 2001, 9999]
1. [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1. [1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1. [1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1. [1, 2, 3, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1. [1, 2, 3, 10, 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1. [1, 2, 3, 10, 11, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 0, 0, 0, 0, 0, 0, 0, 0]
1. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 0, 0, 0, 0, 0, 0, 0]
1. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 0, 0, 0, 0, 0, 0]
1. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 120, 0, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 120, 1000, 0, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 120, 1000, 2000, 0, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 120, 1000, 2000, 2001, 0, 0]
2. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 120, 1000, 2000, 2001, 9999, 0]
5. Copied sortedArr[19] (9999) --> unsortedArr[9] (9999)
4. [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 120, 1000, 2000, 2001, 9999, 9999]
Merged: [1, 2, 3, 10, 11, 12, 35, 36, 37, 49, 51, 59, 99, 100, 120, 1000, 2000, 2001, 9999, 9999]
答案 2 :(得分:0)
合并排序的一般概念是“分而治之”&#34;你应该在第一次连接两个数组,我认为使用Integer对象比使用int变量更好,因为你可以使用类似的函数。
例子:(5.compateTo(6)&gt; 0)将返回false,因为5不大于6.
有一种简单的方法可以做到。
Integer[] conca(Integer[] array1, Integer[]array2)
{
Integer[] tempo = new Integer[array1.length + array2.length];
for(int i = 0; i < array1.length; i++)
{
tempo[i] = array1[i];
}
for(int i = array1.length; i < array2.length; i++)
{
tempo[i] = array2[i];
}
return tempo;
}
现在您有一个简单的数组要排序,您可以使用合并排序算法例程对其进行排序。
这是您使用不同参数调用私有方法的公共方法。 合并排序需要第二个包含已排序数组的数组。
public static void mergeSort(Integer[] a)
{
Integer[] tempo = new Integer[a.length];
mergeSort(a, tempo, 0, a.length - 1);
}
现在是私有方法。
/**
* Internal method that makes recursive calls
* @param a an array of Comparable items
* @param tempo an array to place the merged result
* @param left the left-most index of the subarray
* @param right the right-most index of the subarray
*/
private static void mergeSort(Integer[] a, Integer[] tempo, int left, int right)
{
if(left < right)
{
int center = (left + right) / 2;
mergeSort(a, tempo, left, center);
mergeSort(a, tempo, center + 1, right);
merge(a, tempo, left, center + 1, right);
}
}
/**
* Internal method that merges two sorted halves of a subarray
* @param a an array of Comparable items
* @param tempo an array to place the merged result
* @param leftpos the left-most index of the subarray
* @param rightpos the index of the start of the second half
* @param rightend the right-most index of the subarray
**/
private static void merge(Integer[] a, Integer[] tempo,
int leftpos, int rightpos, int rightend)
{
int leftend = rightpos - 1;
int tempos = leftpos;
int nbelement = rightend - leftpos + 1;
while(leftpos <= leftend && rightpos <= rightend)
{
if(a[leftpos].compareTo(a[rightpos]) <= 0)
{
tempo[tempos++] = a[leftpos++];
}
else
{
tempo[tempos++] = a[rightpos++];
}
}
while(leftpos <= leftend)
{
tempo[tempos++] = a[leftpos++];
}
while(rightpos <= rightend)
{
tempo[tempos++] = a[rightpos++];
}
for(int i = 0; i < nbelement; i++, rightend--)
{
a[rightend] = tempo[rightend];
}
}
来源:
Java中的数据结构和算法分析
第三版
马克艾伦韦斯