Shellsort,2.48 ^(k-1)vs Tokuda的序列

时间:2014-02-02 08:35:40

标签: c# algorithm sorting shellsort

简介

Shellsort是一个有趣的排序算法,我刚才遇到过。最令人惊讶的是,不同的间隙序列可以显着提高算法的速度。我做了一些阅读(不是很广泛),似乎Tokuda的序列被推荐用于实际应用。

另一个有趣的部分是比率2.20~2.25的顺序往往更有效。所以我做了一个小搜索,考虑了从2.20到2.50的比率序列,并尝试搜索哪个比率可以表现平均好。我发现这个比例:2.48在许多不同的试验中看起来平均表现良好。

然后,我想出了序列生成器:2.48 k-1 (让我们称之为248序列)并试图将它与Tokuda的序列进行比较。事实证明,它们的平均速度相等。 248个序列倾向于使用稍多的比较。

基准测试方法

  • 我使用的是比较次数和交换次数,而不是使用毫秒作为度量。
  • 我按照以下数组大小(50,000; 100,000; 200,000; 300,000; 500,000; 1,000,000)进行了100次试验,并记录了它们的比较次数和交换次数。
  • 以下是我的数据(here in CSV format)。
  • 完整代码:http://pastebin.com/pm7Akpqh

问题

我知道我可能错了,这就是为什么我来这里寻求更有经验的程序员的更多意见。如果你没有得到问题,这是我的问题:

  • 2.48 k-1 和Tokuda的序列一样好吗?
  • 如果它与Tokuda的序列一样好,使用它会更实际,因为2.48 k-1 序列比Tokuda的序列更容易生成。

248 Sequence:
  ROUNDUP ( 2.48(k-1) )
  eg: 1, 3, 7, 16, 38, 94, 233, 577, 1431, 3549, 8801, 21826, ...

Tokuda's Sequence
  ROUNDUP ( (9k - 4k) / (5 * 4k - 1) )
  eg: 1, 4, 9, 20, 46, 103, 233, 525, 1182, 2660, 5985, 13467, ...

由于@woolstar建议我也测试边缘情况,例如反转和排序。正如预期的那样,248序列在边缘情况下更快,因为248序列间隙更大,因此它更快地移动逆。


Shellsort实施

public static int compare = 0;
public static int swap = 0;

public static bool greaterthan(int a, int b) {
    compare++;
    return a > b;
}

public static int shellsort(int[] a, int[] gaps) {
    // For keeping track of number of swap and comparison
    compare = 0;
    swap = 0;

    int temp, gap, i, j;

    // Finding a gap that is smaller than the length of the array
    int gap_index = gaps.Length - 1;
    while (gaps[gap_index] > a.Length) gap_index--;

    while (gap_index >= 0) {

        // h-sorting
        gap = gaps[gap_index];
        for (i = gap; i < a.Length; i++) {
            temp = a[i];
            for(j = i; (j >= gap) && (greaterthan(a[j - gap], temp)); j -= gap) {
                a[j] = a[j - gap];
            }

            // swapping
            a[j] = temp;
            swap++;
        }

        gap_index--;
    }

    return compare;
}

1 个答案:

答案 0 :(得分:4)

根据this reserach(Ciura,Marcin(2001)“Shellsort平均案例的最佳增量”。在Freiwalds,Rusins。第13届计算理论基础国际研讨会论文集。伦敦:Springer-Verlag。pp.106-117)对于大小小于10 8 元素的数组,shell排序的主导操作应该是比较操作,而不是交换:

  

Knuth的讨论假设运行时间可近似为9×移动次数,   而图3和图4显示,对于每个序列,关键比较的数量是比运动次数更好的运行时间测量。对于N≤10 8 ,每次移动9个周期的渐近比率不太精确,并且,如果某个假设序列使得Θ(NlogN)移动,则永远不会达到。其他计算机体系结构的类比图将得出相同的结论。

     

当主导行动导致错误的结论时,对待行动   关于最佳序列。

在这种情况下,你的问题的答案是否定的:248序列更糟糕,因为它使用了更多的比较。你也可以考虑将你的序列与本文中提到的Ciura序列进行比较,因为这项研究似乎证明它比Tokuda的序列更好。