结合排序列表工作7/10次

时间:2014-03-23 01:46:27

标签: java arrays

我编写了一些代码,将两个已排序的数组合并为一个已排序的数组。我纯粹是出于学习目的而这样做。我编写了自己的代码(没有查看它是如何完成的)并且遇到了一个奇怪的错误。我的代码大约在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++];

        }
    }

3 个答案:

答案 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中的数据结构和算法分析

第三版

马克艾伦韦斯