在C 中实现Shell排序序列

shell sort sequence implementation in C++

本文关键字:排序 Shell 实现      更新时间:2023-10-16

我正在阅读Robert Sedwick的C 算法中的Shell排序。

此处的外回路要更改增量导致这种紧凑的Shellsort实现,该实现使用了增量序列1 4 13 40 121 364 1093 3280 9841。。。。

template <class Item>
void shellsort(Item a[], int l, int r)
{
    int h;
    for (h = 1; h <= (r - l) / 9; h = 3 * h + 1);
    for (; h > 0; h = h / 3)
    {
        for (int i = l + h; i <= r; i++)
        {
            int j = i; Item v = a[i];
            while (j >= l + h && v < a[j - h])
            {
                a[j] = a[j - h]; j -= h;
            }
            a[j] = v;
        }
    }
}

我的问题是在哪个基础作者检查条件H&lt; =(r-l)/9的情况下,以及为什么作者除以9。

循环:

for (h = 1; h <= (r - l) / 9; h = 3 * h + 1);

计算h的初始值。此值必须小于以下范围:

h <= (r - l)

每次此条件都通过,h都会更新为3 * h + 1,这意味着即使h小于(r-l),更新的值也可能更大。为了防止这种情况,我们可以检查h的下一个值是否会超过最大的索引:

(h * 3) + 1 <= (r - l)

这将确保h小于数组范围。

例如:说我们的尺寸为42,这意味着索引从0到41。使用上述条件:

h = 1, is (3 * 1 + 1) <= (41 - 0) ? yes! -> update h to 4
h = 4, is (3 * 4 + 1) <= (41 - 0) ? yes! -> update h to 13
h = 13, is (3 * 13 + 1) <= (41 - 0) ? yes! -> update h to 40
h = 40, is (3 * 40 + 1) <= (41 - 0) ? no! => h will begin at 40

这意味着我们的初始h是40,因为h仅略小于数组范围,很少完成工作,算法只会检查以下内容:

  1. 数组[40]是否需要用数组[0]?
  2. 交换
  3. 数组[41]是否需要用数组[1]?
  4. 交换

这有点没用,第一次迭代只能执行两次检查。h的初始值较小意味着在第一次迭代中将完成更多的工作。

使用:

h <= (r - l) / 9

确保h的初始值足够小,以允许第一次迭代做有用的工作。作为额外的优势,它看起来也比以前的条件更干净。

您可以用大于3的值替换9个值?为什么要大于3?确保(h * 3) + 1 <= (r - l)仍然是正确的!

,但请记住不要使初始h太小:Shell排序基于插入排序,该排序仅在小或几乎排序的数组上表现良好。就个人而言,我不会超过h <= (r - l) / 15