【问题标题】:InsertionSort vs ShellSort with Gap Size = 1?间隙大小 = 1 的 InsertionSort 与 ShellSort?
【发布时间】:2015-08-21 06:24:38
【问题描述】:

我有两个实现,用于两种不同的排序,InsertionSort 和 ShellSort。

它们如下:

插入排序:

for (int pos = 0; pos < arrayToBeSorted.length; pos++) {
    for (int secondMarker = pos; secondMarker > 0; secondMarker--) {
        int currentValue = arrayToBeSorted[secondMarker];
        int valueBeingCheckedAgainst = arrayToBeSorted[secondMarker - 1];
        if (currentValue > valueBeingCheckedAgainst) {
            break;
        }
        arrayToBeSorted[secondMarker] = arrayToBeSorted[secondMarker - 1];
        arrayToBeSorted[secondMarker - 1] = currentValue;
    }
}

ShellSort:

for (int gap = a.length / a.length; gap > 0; gap = (gap / 2)) {
    for (int i = gap; i < a.length; i++) {
        int tmp = a[i];
        int j = i;
        for (; j >= gap && tmp < (a[j - gap]); j -= gap) {
            a[j] = a[j - gap];
        }
        a[j] = tmp;
    }
}

我还有 10 个整数数组,其中包含 32000 个整数。我得到了在这些类中调用静态 sortArray 方法之前的时间。结果如下:

对于 InsertionSort.sortArray:

Solving array with: 32000 elements.
Time in milliseconds:264
Time in milliseconds:271
Time in milliseconds:268
Time in milliseconds:263
Time in milliseconds:259
Time in milliseconds:257
Time in milliseconds:258
Time in milliseconds:260
Time in milliseconds:259
Time in milliseconds:261

对于 ShellSort:

Solving array with: 32000 elements.
Time in milliseconds:357
Time in milliseconds:337
Time in milliseconds:167
Time in milliseconds:168
Time in milliseconds:165
Time in milliseconds:168
Time in milliseconds:167
Time in milliseconds:167
Time in milliseconds:166
Time in milliseconds:167

那么他们之间怎么会有这么大的区别呢?它们基本上是相同的算法?

另外,ShellSort 的前 2 次运行怎么可能需要更长的时间,但其余的更快?

这是128000个元素的结果,再次先插入排序:

Solving array with: 128000 elements.
Time in milliseconds:4292
Time in milliseconds:4267
Time in milliseconds:4241
Time in milliseconds:4252
Time in milliseconds:4253
Time in milliseconds:4248
Time in milliseconds:4261
Time in milliseconds:4260
Time in milliseconds:4333
Time in milliseconds:4261

ShellSort:

Solving array with: 128000 elements.
Time in milliseconds:5358
Time in milliseconds:5335
Time in milliseconds:2676
Time in milliseconds:2656
Time in milliseconds:2662
Time in milliseconds:2654
Time in milliseconds:2661
Time in milliseconds:2656
Time in milliseconds:2660
Time in milliseconds:2673

我确信我传递给方法的数组是完全相同的,而且它们非常随机。

【问题讨论】:

    标签: java algorithm sorting insertion-sort shellsort


    【解决方案1】:

    在您的插入排序中,您变得更加复杂,

    for (int pos = 0; pos < arrayToBeSorted.length; pos++) {
        for (int secondMarker = pos; secondMarker > 0; secondMarker--) {
            int currentValue = arrayToBeSorted[secondMarker];
            int valueBeingCheckedAgainst = arrayToBeSorted[secondMarker - 1];
            if (currentValue > valueBeingCheckedAgainst) {
                break;
            }
            arrayToBeSorted[secondMarker] = arrayToBeSorted[secondMarker - 1];
            arrayToBeSorted[secondMarker - 1] = currentValue;
        }
    }
    

    你在内部循环中从数组中读取值,当前面位置的值不小于时,你将两个值写入数组。

    在shell排序中,

    for (int i = gap; i < a.length; i++) {
        int tmp = a[i];
        int j = i;
        for (; j >= gap && tmp < (a[j - gap]); j -= gap) {
            a[j] = a[j - gap];
        }
        a[j] = tmp;
    }
    

    您在内部循环之外读取要放置的值一次,并且在内循环体中只有一次写入,在内循环之后仅写入一次值。

    这样效率更高,因此 shell 排序更快是可以理解的。前两个 shell 排序较慢可能是因为包装

    for (int gap = a.length / a.length; gap > 0; gap = (gap / 2)) {
    

    在注意到 gap 可以替换为 1 并消除包装循环之前,它会混淆 JIT 一段时间。

    【讨论】:

    • 感谢您的回答。我拿了 int currentValue = arrayToBeSorted[secondMarker];跳出循环。 (它不是 arrayToBeSorted[pos]。正如你所说,现在我得到了大约 3300 毫秒的值,但它仍然不如我的 ShellSort 实现快。谢谢。
    • 复制Shell排序代码,但将gap替换为1。那么时间应该相等,或者插入排序快一点。
    猜你喜欢
    • 2020-10-29
    • 2014-02-25
    • 2020-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 2015-03-28
    相关资源
    最近更新 更多