为什么此方法不能正确地对较大的数组进行排序?

时间:2019-03-30 20:58:17

标签: java sorting

我刚接触Java,目前正在学习排序算法。我当时正在制定自己的合并排序算法,但这样做时遇到了一个奇怪的问题。我在下面添加了我的mergeArrays方法的代码(应该合并并排序两个排序的数组),问题是它适用于较小的数字,例如{9,13,89,199}和{1,89,127},但不适用于较大的版本,例如{9,13,89,5000}和{1,89,5001},因为它最终重复第二大数字,即输出{1,9,13,13,89,5000,5000}而不是{1,9, 13、89、5000、5001}。我只是不明白为什么会这样,如果有人可以提供帮助,我将不胜感激!

谢谢!

import java.util.*;

public class MergeSortExample
{
  public Integer[] mergeArrays (Integer[] nums1, Integer[] nums2)
  {
    Integer[] nums = new Integer[nums1.length + nums2.length];

    int nums1First = 0, nums2First = 0;
    for (int i = 0; i < nums.length; i++)
    {
      nums[i] = Math.min (nums1[nums1First], nums2[nums2First]);
      if (nums[i] == nums1[nums1First])
      {
        if (nums1First == nums1.length - 1)
        {
          nums1[nums1First] = Integer.MAX_VALUE;
        }
        else
        {
          nums1First++;
        }
      }
      else if (nums[i] == nums2[nums2First])
      {
        if (nums2First == nums2.length - 1)
        {
          nums2[nums2First] = Integer.MAX_VALUE;
        }
        else
        {
          nums2First++;
        }
      }
    }
    return nums;
  }

  public static void main (String[] args)
  {
    /*Integer[] num1 = {9, 13, 89, 5000};
      Integer[] num2 = {1, 89, 5001}; does not work*/

    Integer[] num1 = {9, 13, 89, 199}; //works
    Integer[] num2 = {1, 89, 127}; //works

    MergeSortExample m = new MergeSortExample ();
    Integer[] testMerge = m.mergeArrays (num1, num2);

    for (int i = 0; i < testMerge.length - 1; i++)
    {
      System.out.print (testMerge[i] + ", ");
    }
    System.out.println (testMerge[testMerge.length - 1]);   
  }
}    

2 个答案:

答案 0 :(得分:2)

Integer表示存在一个对象。在比较与==的对象时,它们通常不是等效的,请考虑与String-s的常见错误。
它适用于小数的原因是它们已被缓存,其中有一个预实例化的小整数集,如valueOf(int i)中所述:

  

public static Integer valueOf(int i)

     

返回代表指定的Integer值的int实例。如果不需要新的Integer实例,则通常应优先于构造方法Integer(int)使用此方法,因为此方法可能会通过缓存经常请求的值而产生明显更好的空间和时间性能。此方法将始终缓存-128至127(包括)范围内的值,并且可能会缓存此范围之外的其他值。

当Java将int-s自动装箱到Integer-s中时,可以假定使用此方法。

解决方案:请勿这样做,请使用int数组。然后它将突然起作用。

您可以尝试的简单测试代码:

Integer a127=127;
Integer b127=127;
Integer a5000=5000;
Integer b5000=5000;
System.out.println(a127+"=="+b127+"? "+(a127==b127));
System.out.println(a5000+"=="+b5000+"? "+(a5000==b5000));

(查看有关Ideone的实际操作:https://ideone.com/vEry18


旁注:虽然对称性很好,但我会考虑使用<(或>)而不是那种Math.min()的魔法,即使它会导致写成nums[i] =两次:

if (nums1[nums1First] < nums2[nums2First])
{
  nums[i] = nums1[nums1First];
  if (nums1First == nums1.length - 1)
  {
    nums1[nums1First] = Integer.MAX_VALUE;
  }
  else
  {
    nums1First++;
  }
}
else
{
  nums[i] = nums2[nums2First];
  if (nums2First == nums2.length - 1)
  {
    nums2[nums2First] = Integer.MAX_VALUE;
  }
  else
  {
    nums2First++;
  }
}

答案 1 :(得分:1)

Integer对象上的

==导致了问题。找到代码的修改版本。

public class MergeSortExample {
    public Integer[] mergeArrays(Integer[] nums1, Integer[] nums2) {
        Integer[] nums = new Integer[nums1.length + nums2.length];

        int nums1First = 0, nums2First = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums1First >= nums1.length) {
                nums[i] = nums2[nums2First];
                nums2First++;
            } else if (nums2First >= nums2.length) {
                nums[i] = nums1[nums1First];
                nums1First++;
            } else {
                nums[i] = Math.min(nums1[nums1First], nums2[nums2First]);

                if (nums[i].equals (nums1[nums1First])) {
                    nums1First++;
                } else {
                    nums2First++;
                }
            }

        }
        return nums;
    }

    public static void main(String[] args) {
        Integer[] num1 = { 9, 13, 89, 5000 };
        Integer[] num2 = { 1, 89, 5001 };
        /* does not work */

        // Integer[] num1 = {9, 13, 89, 199}; //works
        // Integer[] num2 = {1, 89, 127}; //works

        MergeSortExample m = new MergeSortExample();
        Integer[] testMerge = m.mergeArrays(num1, num2);

        for (int i = 0; i < testMerge.length; i++) {
            System.out.print(testMerge[i] + ", ");
        }
    }
}

输出:

enter image description here