【问题标题】:java.lang.StackOverflowError in MergeSort合并排序中的 java.lang.StackOverflowError
【发布时间】:2017-03-09 08:36:12
【问题描述】:
public class MergeSort
{
public static double[] MergeSort(double[] a){
    if(a.length < 1){
        return new double[0];
    }
    else if(a.length == 1){
        return a;
    }
    else{
        double[] l = Teiler(a, false);
        double[] r = Teiler(a, true);
        return Fueger(MergeSort(l), MergeSort(r));
    }
}
...
}

public static double[] Fueger(double[] a, double[] b): 返回一个包含 a 和 b 中正确顺序的所有数字的双精度数组。

public static double[] Teiler(double[] a, boolean l): 返回一半的元素(前半部分,如果 l 为假,后半部分,如果 l 为真)

Fueger 和 Teiler 工作得很好,但 MergeSort 总是给出 java.lang.StackOverflowError,即使当数组为空或只包含一个元素时递归应该终止。 有什么问题?

感谢您的帮助

这里是弗格:

public static double[] Fueger(double[] a, double[] b){
    double[] hilf = new double[a.length + b.length];
    int i = 0;
    while((a.length != 0) && (b.length != 0)){
        if(a[0] < b[0]){
            hilf[i] = a[0];
            a = Weg(a);
        }
        else{
            hilf[i] = b[0];
            b = Weg(b);
        }
        i++;
    }
    if(a.length != 0){
        for(double x : a){
            hilf[i] = x;
            a = Weg(a);
            i++;
        }
    }
    if(b.length != 0){
        for(double x : b){
            hilf[i] = x;
            b = Weg(b);
            i++;
        }
    }
    return hilf;
}

提勒:

public static double[] Teiler(double[] a, boolean r){
    double[] hilf;
    int x = 0;
    if(r == false){
        hilf = new double[(int) a.length / 2];
        for(int i = 0; i < a.length / 2; i++){
            hilf[x] = a[i];
            i ++;
        }
    }
    else{
        hilf = new double[(int) (a.length / 2) + 1];
        for(int i = a.length / 2; i < a.length; i++){
            hilf[x] = a[i];
            i ++;
        } 
    }
    return hilf;
}

【问题讨论】:

  • 我怀疑堆栈跟踪是否会有所帮助。我怀疑这只是MergeSort 调用自身的大量行。看到Teiler 方法会更有用 - 我感觉这可能是错误所在。
  • @TobiasWeißberg 为什么是a.length / 2 + 1?当a.length == 2 时会发生什么?
  • 我也认为问题出在a.length / 2 + 1,如果您考虑2 个元素的列表Teiler(a, true) 返回一个长度为2 的数组(即使它只填充第一个元素)。我认为您可以通过(a.length / 2) + (a.length % 2) 解决此问题
  • 为什么在 kennytm 和我都指出问题出在这之后,你删除了 Teiler?您是否试图让人们难以回答?
  • @AimeeBorda 这是正确的答案,如果您将其作为答案发布,我会投票赞成。基本上,如果 a 的长度为 2,而 r 的长度为 true,则 Teiler 当前返回长度为 2 的数组。这会将递归陷入无限循环中。

标签: java sorting stack-overflow mergesort


【解决方案1】:

问题出在 Teiler 方法中。考虑一个长度为 2 的列表,else 分支创建一个长度为 2 而不是 1 的列表(即使它只填充第一个元素)。因此,将递归陷入无限循环。您可以通过仅在长度为奇数时添加最后一个元素来轻松解决此问题:

public static double[] Teiler(double[] a, boolean r){
   double[] hilf;
   int x = 0;
   if(r == false){
       hilf = new double[(int) a.length / 2];
       for(int i = 0; i < a.length / 2; i++){
           hilf[x] = a[i];
           i ++;
       }
   } else{
       hilf = new double[(int) (a.length / 2) + (a.length % 2)];
       for(int i = a.length / 2; i < a.length; i++){
           hilf[x] = a[i];
           i ++;
       } 
   }
   return hilf;
}

【讨论】:

  • 这是绝对有效的方式——但我喜欢写诸如int bottomSize = a.length/2; int topSize = a.length-bottomSize; 之类的东西,我们关心另一半的剩菜。
  • @ArturBiesiadowski 很公平:)
猜你喜欢
  • 2016-02-12
  • 2019-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-04
  • 1970-01-01
  • 2016-08-09
  • 2015-03-27
相关资源
最近更新 更多