【问题标题】:Arrays.sort(Object[] a) - how is it implemented?Arrays.sort(Object[] a) - 它是如何实现的?
【发布时间】:2010-02-07 19:45:16
【问题描述】:

有没有关于如何实现 Arrays.sort(Object[] a) 使用的 mergeSort 的资源?虽然它的文档很好,但我很难理解它(特别是为什么在递归调用 mergeSort() 时会切换 src 和 dest)。

【问题讨论】:

  • 博卓,你应该已经发布了一个答案!
  • 看起来真正的工作从第 486 行开始。
  • @Will,是的,也许。就这样。
  • JDK7 不会有 Tim Sort 或双轴 Quicksort 之类的吗?

标签: java algorithm mergesort


【解决方案1】:

Here is the source 中的java.util.Arrays

实际上,您在 JDK 中有该源代码 - 只需在您的 IDE 中打开 java.util.Arrays,源代码 + cmets 就会出现。如果您没有 IDE,请查看JDK_HOME\src.zip

然后,将其放入您的 IDE 并跟踪其工作原理。

  • 设置断点(并在调试模式下运行程序)
  • 使用System.out.println(..)
  • 更改部分内容以查看它们是如何反映的。
  • 阅读wikipedia article about merge sort
  • 关注此评论:// Recursively sort halves of dest into src

【讨论】:

  • 出现 OP 已经看到了源代码(因为他/她提到了 srcdest 数组在递归调用时被切换)但是有一个很难理解逻辑。
  • 嗯,是的。我就如何更好地理解它给出了一些指示。
  • 我当然可能是错的......无论如何,我打算建议 OP 使用 poor-man's debugger(在算法),但你打败了我!
  • :) 它在原始答案中,但没有太多指出。
  • 谢谢,不知道 src.zip 中的源代码。我只阅读了 Eclipse 打开但我无法调试的类文件(这是有道理的 ^^)。但是有了源码,我可以修改代码,放一些断点,终于意识到它是如何工作的。
【解决方案2】:

我曾经和你有过同样的困惑。据我了解,这种切换的原因很简单——让后面的合并步骤更容易。没有魔法。

    private static void mergeSortWithoutSwitch(Object[] src, Object[] dest, int low, int high, int off) {
    int length = high - low;

    // Insertion sort on smallest arrays
    if (length < INSERTIONSORT_THRESHOLD) {
        for (int i = low; i < high; i++)
            for (int j = i; j > low && ((Comparable) dest[j - 1]).compareTo(dest[j]) > 0; j--)
                swap(dest, j, j - 1);
        return;
    }

    // Recursively sort halves of dest into src
    int destLow = low;
    int destHigh = high;
    low += off;
    high += off;
    int mid = (low + high) >>> 1;
    mergeSortWithoutSwitch(src, dest, low, mid, off);
    mergeSortWithoutSwitch(src, dest, mid, high, off);

    // If list is already sorted, just copy from src to dest. This is an
    // optimization that results in faster sorts for nearly ordered lists.
    if (((Comparable) dest[mid - 1]).compareTo(dest[mid]) <= 0) {
        return;
    }

    // Merge sorted halves (now in src) into dest
    for (int i = destLow, p = low, q = mid; i < destHigh; i++) {
        if (q >= high || p < mid && ((Comparable) dest[p]).compareTo(dest[q]) <= 0)
            src[i] = dest[p++];
        else
            src[i] = dest[q++];
    }

    // copy back
    for (int i = destLow; i < destHigh; i++) {
        dest[i] = src[i];
    }

}

以上是没有切换的实现,从代码中可以看出我们还需要一步合并——copy back。我觉得mergeSort中的参数命名有点混乱,因为src是辅助数组,只在合并步骤中使用,最好用aux命名(我们甚至可以从方法签名中删除它,并创建一个局部变量合并时)。 dest 是结果数组。

【讨论】:

    猜你喜欢
    • 2023-02-15
    • 2015-09-26
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    相关资源
    最近更新 更多