C ++中的shell排序顺序实现

时间:2015-05-04 12:08:38

标签: c++ algorithm sorting shellsort

我正在阅读Robert Sedwick的C ++ Algorithms中的shell排序。

这里改变增量的外部循环导致这种紧凑的shellort实现,它使用增量序列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。

1 个答案:

答案 0 :(得分:1)

循环:

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. 数组[41]是否需要与数组[1]交换?
  3. 这有点无用,第一次迭代只执行两次检查。较小的初始值h意味着在第一次迭代中将完成更多的工作。

    使用:

    h <= (r - l) / 9
    

    确保h的初始值足够小,以允许第一次迭代执行有用的工作。作为额外的优势,它看起来也比之前的情况更清晰。

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

    但请记住不要使初始h太小:Shell Sort基于Insertion Sort,它只能在小型或接近排序的数组上运行良好。就个人而言,我不会超过h <= (r - l) / 15