【问题标题】:Efficient Mergesort Confusion高效的合并排序混乱
【发布时间】:2013-04-13 08:41:23
【问题描述】:

我从昨天开始一直在阅读mergesort example(高效的),尽管查看了代码,但我仍然无法理解它是如何工作的:

private static void sort(int[] list) {
    a = list;
    int n = a.length;
    // according to variant either/or:
    b = new int[n];
    b = new int[(n + 1) / 2];
    mergesort(0, n - 1);
}

private static void mergesort(int first, int last) {
    if (first < last) {
        int mid = (first + last) / 2;
        mergesort(first, mid);
        mergesort(mid + 1, last);
        merge(first, mid, last);
    }
}

到目前为止,理解算法没有问题,但困惑在于以下方法:

private static void merge(int first, int mid, int last) {
    int i, j, k;

    i = 0;
    j = first;

    while (j <= mid)
        b[i++] = a[j++]; // *j's value is now mid*

    i = 0; // *i is reset to 0, nothing's been done to j*
    k = first;


    // *before entering the following while loop, j still carries mid's value*
    while (k < j && j <= last)
        if (b[i] <= a[j])
            a[k++] = b[i++];
        else
            a[k++] = a[j++];        

    // copy back remaining elements of first half (if any)
    while (k < j)
        a[k++] = b[i++];
}

进入第二个while循环while (k &lt; j &amp;&amp; j &lt;= last)是我不明白这种排序是如何工作的。据我了解,数组a的前半部分已经复制到辅助数组b,现在我们想通过比较a[j++](后半部分)和辅助数组@987654328来排列整个数组@ 这样我们就可以得到较小的数组元素,并将其放入数组a 中,对数组进行升序排序。

但为什么是while (k &lt; j &amp;&amp; j &lt;= last)? k &lt; j 听起来很合乎逻辑,因为我们需要从辅助数组中取回所有值,但为什么是 j &lt;= last?为什么我们不能只做while (k &lt;= last)?

另外,有人可以确认我对上述代码中 j 值的理解是正确的吗?

【问题讨论】:

  • 可以从 URL 中删除 "。

标签: algorithm sorting merge while-loop mergesort


【解决方案1】:

k &lt; j表示辅助数组b仍然包含元素

j &lt;= last表示a的第二部分仍然包含元素

我们不能在这里使用k &lt;= last,因为当j变成last+1时,我们可能会访问数组a索引超出边界

对于 cmets 来说太长了,在此补充:

当可用内存有限(大型数据集)时,此变体很有用。在一些教程中提到了它(我在 J.Bucknall 关于 Delphi 算法的书中遇到过它)。它是稳定的( if (b[i] a[j]) 保持稳定。它通常不会更快,因为最好不要复制数据,但是,例如,'在每个阶段触发'源和目标数组(指针)

【讨论】:

  • 感谢您的回答。我还想问一下——上面的合并排序有多常见?我经历了很多归并排序教程,其中没有提到第二个数组的构造只有原始数组的一半大小以提高效率。这种实施是以稳定性为代价的吗?最重要的是,这真的更快吗?
  • 另外,我们是否可以说 k 还有未排序且未放置的元素?因为 k 永远不会到达 j 除非最后一个元素已经到位。
  • 第二个问题 - 是的,你是对的。 1t 问题 - 添加在答案中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多