【问题标题】:Shell Vs. Hibbard time complexity comparison壳牌VS。 Hibbard 时间复杂度比较
【发布时间】:2015-08-24 18:21:54
【问题描述】:

我正在做一个实验来比较 Thomas Hibbard 的 shell 排序(间隙大小 = 2^k-1)和 Donald Shell 的 shell 排序(n/2^k)在同一个数组上的执行情况。当数组的大小从 10 到 1000 时,Hibbard 的性能优于 shell。但是当大小达到 10000 或更高时,shell 排序比 Hibbard 快。

按照大O表示法,Hibbard是O(N^1.5),Shell是O(N^2),这让我觉得随着数据集规模的增加,Hibbard应该比Shell有更大的改进。谁能告诉我为什么我的结果可能不如预期?

我知道 O 表示法是最坏情况下的复杂度,但似乎性能应该更好地与该表示法保持一致。

这是我用 JAVA 编写的代码: (注意:unsortedArray 之前已声明并初始化)

{
    int temp;
    int[] sortedArray = unsortedArray.clone();
    printArray();
    int k = (int)(Math.log(sortedArray.length)/Math.log(2));
    int gap = (int)(Math.pow(2,k)-1);
    int count = 0;
    long endTime;
    long startTime = System.nanoTime();

    while (gap > 0)
    {
        for (int g = 0; g < gap; g++)
        {
            for (int d = g + gap; d < sortedArray.length; d = d + gap)
            {
                for (int i = d; i - gap >= 0; i = i - gap)
                {                          
                    if (sortedArray[i - gap] <= (sortedArray[i]) )
                    {
                        break;
                    }
                    count++;
                    temp = sortedArray[i];
                    sortedArray[i] = sortedArray [i-gap];
                    sortedArray[i-gap] = temp;

                }
            }
        }

        k = k -1;
        gap = (int)(Math.pow(2,k)-1);
    }
    endTime = System.nanoTime();
    System.out.println("The total time for hibbard sort is" + (endTime-startTime));
    System.out.println("the number of swaps for hibbard sort is" + count);
}

【问题讨论】:

  • 请注意该代码用于 Hibbard 的 shell 排序。
  • 根据“缓存未命中”而不是“交换”或“比较”来衡量复杂性可能会提供信息。

标签: algorithm sorting time-complexity shellsort


【解决方案1】:

我认为性能可能会受到 JVM 的影响,因此最好用另一种语言(如 C 或 C++)来衡量它。

更多关于 Java、C++ 和 C# 中的 Shell 排序算法的信息可以在这里找到:

http://www.programming-algorithms.net/article/41653/Shell-sort

这里有关于测量算法复杂度的信息:

http://www.programming-algorithms.net/article/44682/Asymptotic-complexity

希望对您有所帮助。

【讨论】:

    【解决方案2】:

    测量这两种间隙生成算法之间的时间复杂度差异实际上比这要复杂一些。

    考虑为两者提供排序的数据序列并假设 n=8。对于 Shell,我们得到 {4,2,1} 和 Hibbard {7,3,1} 的间隙序列。要运行排序序列将需要 (Shell) (n-4)+(n-2)+(n-1) 或 17 次比较和 (Hibbard) (n-7)+(n-3)+(n- 1) 或 13.

    很明显,在给定 n 个元素的随机序列的情况下,您无法得出 Hibbard 将在 Shell 的 13/17 时间执行的结论。

    可能会发现给定的随机生成的序列比 Hibbard 更适合使用 Shell 进行排序,反之亦然。确定哪个更好的唯一方法是测试所有可能的数据序列组合并计算它们所需的平均比较次数。当 n=8(只有 n! 或 40320 种组合)时,这很容易完成,但是当 n=100 或 1000 时,“更多”就很困难了。

    当 n=8 时,使用上述两个间隙对所有可能的序列进行 Shellsort(插入排序和最佳 Shellsort 间隙用于比较):

                           number of comparisons when n=8
    gap sequence           minimum   average   maximum   reverse
    {1} (insertion sort)      7       19.28      28        28
    {5,1} (best gap)         10       17.4       24        15 
    {4,2,1} (Shell)          17       21.82      30        22
    {7,3,1} (Hibbard)        13       18.57      24        20
    

    所以在 n=8 的情况下,Hibbard 比 Shell 好得多,比插入排序好,但比最佳间隙序列差。有趣的是,为了获得最佳间隙,对反向数据序列进行排序比平均情况要快!

    如果我们查看 n=14,我们会发现 Shell 和 Hibbard 产生相同的序列,{7,3,1} - 显然这两种算法都不会比另一种更好 - 在 n=16 时,我们得到 {8 ,4,2,1} 和 {15,7,3,1},分别。这导致 Hibbard (n*4)-(15+7+3+1) 或 38 次比较的最佳情况比 Shell (n*4)-(8+4+2+1) 或 49 更好。

    随着 n 的增加,哪个会比另一个更好?在我看来,最好的间隙序列取决于 n,这应该给 Shell 带来优势,例如 Hibbard 具有相同的序列 {7,3,1} 当 8

    Shellsort 希望移动初始间隙中相距较远的值,而当 n=16、17 或 18 且间隙为 15 时,这对 Hibbard 来说可能是正确的,但当 n 接近上限时,这种情况就不太正确了限制为 31。

    但是,这并不是说 Shell 会产生更好的间隙序列。当 n 接近序列的上限时,n/2 的第一个间隙将始终受到与 Hibbard 的初始间隙相同的问题的阻碍。

    所以我的猜测是,Shell 会给出比 Hibbard 更差的稳定结果,而且可能还有插入排序。 Hibbard 的初始差距从下限到上限 n 的结果将不成比例地增加。在某个地方,当 n 接近 n 上限时,Hibbard 的性能也会开始比插入排序更差。

    除了计算间隙本身的值之外,还必须确定间隙的数量。如前所述,当 n=8 时,两个间隙就足够了,但当 n=10 或更多时,这是否也是正确的?例如,从 2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-06
      • 1970-01-01
      • 1970-01-01
      • 2021-04-17
      • 2015-10-14
      • 1970-01-01
      相关资源
      最近更新 更多