【问题标题】:Two different answers when using variables that should be the same (mergeSort)使用应该相同的变量时的两个不同答案(mergeSort)
【发布时间】:2018-04-02 21:43:42
【问题描述】:

我有点困惑,正在寻找一些澄清,所以我正在研究数据结构和算法,并且正在研究归并排序。本质上,我想返回排序列表并打印它以测试我是否正确实现了代码,但是懒惰的科学家决定不将数据复制回原始数组,而只返回临时数组。我注意到,当我最后返回 temp 时,我会得到与复制回来后返回原始数组(名为 a)不同的答案。想知道是否有人可以解释为什么会发生这种情况。谢谢!下面是正确打印的代码,如果您在 merge 方法中将 return 更改为 temp,您会注意到列表停止正确排序

public class mergeSort {

public static void main(String[] args) {

    int[] a = new int[10];

    for(int i = 0; i < a.length; i++) {

        a[i] = (int)(Math.random()*30+1);
        System.out.println(i + ": " + a[i]);
    }

    mergeSort(a);
}

public static void  mergeSort(int[] a) {


    int[] temp = new int[a.length];

    a = mergeSort(a, 0, a.length, temp);

    for(int i = 0; i < a.length; i++){

        System.out.println(a[i]);
    }

}

public static int[] mergeSort(int[] a, int start, int end, int[] temp) {

    int mid;


    //Recursive method
    if(1 < end-start) {

        mid = start + (end-start)/2;
        mergeSort(a, start, mid, temp);
        mergeSort(a, mid, end, temp);
        a = merge(a, start, mid, end, temp);
    }

    return a;


}

public static int[] merge(int[] a, int start, int mid, int end, int[] temp) {


    int currL = start;
    int currR = mid;
    int currT;

    for(currT = start; currT < end; currT++) {

        if(currL < mid && (currR >= end || a[currL] < a[currR])) {

            temp[currT] = a[currL];
            currL++;
        }

        else{

            temp[currT] = a[currR];
            currR++;
        }

    }

    for(currT = start; currT < end; currT++) {
        a[currT] = temp[currT];
    }

    return a;

} 
}

【问题讨论】:

    标签: java arrays sorting recursion mergesort


    【解决方案1】:

    考虑:

    mergeSort(a, 0, 10, temp);
    

    它调用:

    mergeSort(a, 0, 5, temp);
    mergeSort(a, 5, 10, temp);
    a = merge(a, 0, 5, 10, temp);
    

    mergeSort(a, 0, 5, temp)返回后,子数组a[0]到a[5]必须排序,mergeSort(a, 5, 10, temp)返回后,子数组a[5]到a[10]必须排序。

    如果merge 不修改原始数组a 接收,则不会发生这种情况。

    请注意,赋值 a = merge(a, start, mid, end, temp); 不会更改传递给 mergeSort 方法的原始数组。因此merge 本身必须修改传递给它的数组a,将temp 数组中的数据复制回a

    编辑:

    顺便说一句,请注意merge 返回的内容并不重要,只要它将合并的元素从temp 数组复制回a 数组即可。

    您可以将其返回类型更改为void,排序仍然有效:

    public static void mergeSort(int[] a, int start, int end, int[] temp) {
        int mid;
        //Recursive method
        if(1 < end-start) {
            mid = start + (end-start)/2;
            mergeSort(a, start, mid, temp);
            mergeSort(a, mid, end, temp);
            merge(a, start, mid, end, temp);
        }  
    }
    
    public static void merge(int[] a, int start, int mid, int end, int[] temp) {
        int currL = start;
        int currR = mid;
        int currT;
    
        for(currT = start; currT < end; currT++) {
            if(currL < mid && (currR >= end || a[currL] < a[currR])) {
                temp[currT] = a[currL];
                currL++;
            } else {
                temp[currT] = a[currR];
                currR++;
            }
        }
        for(currT = start; currT < end; currT++) {
            a[currT] = temp[currT];
        } 
    }
    

    【讨论】:

    • 非常感谢您写的这么好的答案!关于不需要退货的好处,应该早点发现。干杯的朋友!
    • @OVOFan - 您可以通过根据自上而下的递归级别或自下而上的传递更改合并方向来消除复制步骤。有关自下而上和自上而下的示例,请参阅 this answer
    猜你喜欢
    • 1970-01-01
    • 2020-01-30
    • 2012-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 2022-11-29
    相关资源
    最近更新 更多