【问题标题】:Recursive merge sort not returning a sorted array递归合并排序不返回排序数组
【发布时间】:2021-03-29 14:12:19
【问题描述】:

我正在编写 3 种方法来实现递归合并排序,但参数数量有限(无 aux、lo、mid、hi)。我认为我所做的工作,但它没有返回排序数组,尽管它运行时没有任何编译错误。我已经摆弄了 4 个小时,似乎无法弄清楚我做错了什么,没有合并有序数组。我只从我的助教那里得到了非常模糊的输入,并且能够解决我遇到的一些问题,但是该方法仍然不能对项目数组进行排序。欢迎就我在这里可能做错的事情提出任何建议。谢谢!

    public static void sort(Comparable[] a) {
        //Sort a recursively
        a = mergeSort(a);
    }
    
    /** 
     * 
     * Method recursively splits array into halves until length becomes 1, then
     * Calls merge to merge the split arrays back together.
     * @param a Comparable[] 
     * @return a Comparable[]
     */
    public static Comparable[] mergeSort(Comparable[] a) {
        if (a.length <= 1) {
            return a;
        } else {
            //create 1st array for D&C, length = 1/2 a.length
            Comparable[] first = new Comparable[a.length / 2]; 
            
            //create 2nd array for D&C, length = a.length - first.length
            Comparable[] second = new Comparable[a.length - first.length]; 
            
            //source/position: a[0], destination/position: first[0], length: first.length
            System.arraycopy(a, 0, first, 0, first.length);      
            
            //source/position: a[first.length], destination/pos: second[0], length: second.length
            System.arraycopy(a, first.length, second, 0, second.length);  
            
            //recursively sort the first half
            first = mergeSort(first);
            
            //recursively sort second half
            second = mergeSort(second);
            
            //merge the halves
            a = merge(first, second);
        }
        
        //return the merged array
        return a;
    }
    
    public static Comparable[] merge(Comparable[] a, Comparable[] b) {
        Comparable[] result = new Comparable[a.length + b.length];
        
        //Index Position in first array - starting with first element
        int first = 0;
         
        //Index Position in second array - starting with first element
        int second = 0;
         
        //Index Position in merged array - starting with first position
        int merged = 0;
         
        //Compare first and second, 
        while (first < a.length && second < b.length) {
            if (a[first].compareTo(b[second]) < 0) {
                result[merged++] = a[first++];
            } else {
                result[merged++] = b[second++];
            }
        }
        
        //Store remaining elements of 1st array
        while (first < a.length) {
            result[merged++] = a[first++];
        }
        
        //Store remaining elements of second array
        while (second < b.length) {
            result[merged++] = b[second++];
        }
        
        //copy elements from both halves - each half will have the sorted elements
        // System.arraycopy(a, first, result, merged, a.length - first);
        // System.arraycopy(b, second, result, merged, b.length - second);
        
        return result;
    }
    

【问题讨论】:

  • 您是否意识到 Java 是按值传递的,即重新分配参数对调用者不可见?所以a = mergeSort(a); 可能没有你期望的效果。
  • 我之前已经删除了它,它仍然在运行而不进行排序,但是在我现在使用的代码中,我已经删除了它,它仍然没有对任何东西进行排序。
  • 好吧,删除那段代码并不意味着解决问题,因为您首先丢失了一段代码。您需要在某处返回排序后的数组才能看到更改。
  • 我能够通过在我的方法中创建一个新对象来正确实现它,以解决正在发生的引用问题,以防止排序后的数组返回到 main

标签: java recursion mergesort


【解决方案1】:

正如@Thomas 所指出的,Java 函数是按值传递的。因此,执行a = mergeSort(a) 不会更改原始数组,而是对传递给函数的副本进行排序。相反,您可以返回结果:

public static Comperable[] sort(Comparable[] a) {
        //Sort a recursively
        return mergeSort(a);
}

这将使用本地值计算所有内容并将其返回给原始“所有者”。

【讨论】:

  • 这里唯一的问题是 sort 有一个 void 类型。所以我不能返回归并排序,我只能运行它并从那里实现归并排序内部的递归。我知道问题发生在 mergesort 或 merge 中的某个地方,但我不确定确切的位置。
  • 另外,我删除了 a = mergesort(a) 并只放置了仍不返回排序数组的 mergesort(a)。
  • 问题不在a = mergesort(a),问题在not returning。您的代码对数组的副本进行排序,但原始代码保持不变。更改原始数组的唯一方法是返回排序数组(有效,我也检查过),我在答案中显示。
  • 我也考虑过这个问题,但问题是我没有选择让 sort(Comparable[] a) 返回值。排序方法必须保持无效,我只能让 mergesort 和 merge 返回一个数组。所以我不确定如何在任务范围内实现这一点。
  • 如何使用调用递归帮助器的 void 方法,同时仍将值返回给 a?在与我的导师交谈后,我意识到问题在于在对 a 的方法调用中没有返回任何内容,但我不知道如何操作 a 的值。
【解决方案2】:

静态方法sort(Comparable[] a) 不会就地修改其数组参数。分配mergeSort(a) 的结果只会修改局部变量a。您应该将此结果复制回参数a 指向的数组中:

    public static void sort(Comparable[] a) {
        //Sort a recursively
        Comparable[] b = mergeSort(a);
        System.arraycopy(b, 0, a, 0, a.length);
    }

【讨论】:

    猜你喜欢
    • 2021-11-06
    • 2019-01-22
    • 2019-09-09
    • 1970-01-01
    • 2020-03-04
    • 2010-12-06
    相关资源
    最近更新 更多