在这种自下而上合并排序的实现中是否存在可能的勘误

时间:2017-04-07 11:44:07

标签: java algorithm sorting mergesort

以下代码片段来自Robert SedgeWick和Kevin Wayne的Algorithms一书。

public class MergeBU {

    // This class should not be instantiated.
    private MergeBU() { }

    // stably merge a[lo..mid] with a[mid+1..hi] using aux[lo..hi]
    private static void merge(Comparable[] a, Comparable[] aux, int lo, int mid, int hi) {

        // copy to aux[]
        for (int k = lo; k <= hi; k++) {
            aux[k] = a[k]; 
        }

        // merge back to a[]
        int i = lo, j = mid+1;
        for (int k = lo; k <= hi; k++) {
            if      (i > mid)              a[k] = aux[j++];  // this copying is unneccessary
            else if (j > hi)               a[k] = aux[i++];
            else if (less(aux[j], aux[i])) a[k] = aux[j++];
            else                           a[k] = aux[i++];
        }

    }

    /**
     * Rearranges the array in ascending order, using the natural order.
     * @param a the array to be sorted
     */
    public static void sort(Comparable[] a) {
        int n = a.length;
        Comparable[] aux = new Comparable[n];
        for (int len = 1; len < n; len *= 2) {
            for (int lo = 0; lo < n-len; lo += len+len) {
                int mid  = lo+len-1;
                int hi = Math.min(lo+len+len-1, n-1);
                merge(a, aux, lo, mid, hi);
            }
        }
        assert isSorted(a);
    }
//other methods
}

我的问题是关于sort方法的内部for循环条件。

如果输入数组有10个元素,则对长度为4的子数组进行合并的数组上的传递将保留最后两个元素,这些元素相对于彼此排序但不与其他元素相关

在下一次传递中,合并的子数组的长度变为8,并且它仍然会使最后两个元素相对于其他元素保持未合并。这是长度为10的数组的最后一次传递。

因此,最后两个元素相对于数组中的其他元素保持未分类,因为lo&lt; n-len检查。本节并未说明数组中元素的数量应该是2的幂。这是勘误还是我遗漏了什么?

我肯定会忽略一些东西,因为以下测试代码正确地对我的10个元素数组进行排序。

public static void main(String[] args) {
        Integer[] array = {1,2,3,4,5,6,7,8,-50, -80};
        MergeBU.sort(array);
        System.out.println(Arrays.toString(array));
    }

有人可以帮我解决。

1 个答案:

答案 0 :(得分:2)

您的分析不正确。合并进行如下。

len = 4的传递中,它将合并两个子阵列[0-3][4-7]。你是正确的,最后两个项目没有合并。

len = 8时,它会合并两个子阵列[0-7][8-9]

我怀疑你在循环控制变量增加时会误解。您应该在调试器中单步执行sort方法,并注意两个循环中lolen的值。

顺便说一句,合并排序的定义中没有任何内容要求长度为2的幂。但是,处理不是2的幂的数组会增加一些复杂性。这就是if (i > mid)循环中if (j > himerge}条件的原因。