【发布时间】:2014-02-25 19:57:22
【问题描述】:
简介
Shellsort 是我不久前遇到的一个有趣的排序算法。最令人惊奇的部分是不同的间隙序列可以显着提高算法的速度。我做了一些阅读(不是广泛阅读),似乎建议将 Tokuda 的序列用于实际应用。
另一个有趣的部分是比率 2.20~2.25 的序列往往更有效。所以我做了一个小的搜索,考虑了从 2.20 到 2.50 的比率序列,并试图搜索哪个比率可以表现平均好。我遇到了这个比率:2.48,这似乎在许多不同的试验中平均表现良好。
然后,我想出了序列生成器:2.48k-1(我们称之为 248 序列)并尝试将其与德田的序列进行比较。事实证明,它们的速度平均相等。 248 序列倾向于使用更多的比较次数。
基准方法
- 我没有使用毫秒作为度量,而是使用比较次数和交换次数。
- 我对以下数组大小(50,000;100,000;200,000;300,000;500,000;1,000,000)分别进行了 100 次试验,并跟踪它们的比较次数和交换次数。
- 以下是我的数据 (here in CSV format)。
- 完整代码:http://pastebin.com/pm7Akpqh
问题
我知道我可能错了,这就是为什么我来这里寻求更多经验丰富的程序员的意见。如果你没有得到这个问题,这里是我的简短问题:
- 2.48k-1 和德田的序列一样好吗?
- 如果它和德田的序列一样好,那么使用它会不会更实用,因为 2.48k-1 序列比德田的序列更容易生成。
248序列: 综述(2.48(k-1)) 例如:1、3、7、16、38、94、233、577、1431、3549、8801、21826、... 德田的序列 ROUNDUP ( (9k - 4k) / (5 * 4k - 1) ) 例如: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;
}
【问题讨论】:
-
你能在这里引用德田的序列吗?我不知道。
-
除了测试随机排序的数据外,测试您的序列如何处理边缘情况,例如完全排序、几乎排序和反转。
-
@JanDvorak,我更新了德田的序列公式。
-
@woolstar,感谢您的想法。我会尝试边缘情况。
-
@woolstar,正如我所测试的,在边缘情况下,248 序列运行得更快,因为差距大于德田的序列。
标签: c# algorithm sorting shellsort