【问题标题】:Implementing shellsort algorithm in C在 C 中实现 shellsort 算法
【发布时间】:2015-08-20 07:04:51
【问题描述】:
void shellsort(int v[], int n)
{
    int gap, i, j, temp;
    for (gap = n/2; gap > 0; gap /= 2)
        for (i = gap; i < n; i++){
            for (j=i-gap; j>=0 && v[j]>v[j+gap]; j-=gap) {
                temp = v[j];
                v[j] = v[j+gap];
                v[j+gap] = temp;
            }
        }
    }
 }

在这个shellsort() 函数中,我们有j-=gap。假设n = 10,差距总是5 和j 从0,1,2,3,4... 递增。

这意味着这个内部for循环运行的前5次,它将向j返回一个负值(例如0-5=-5),因此由于j不会大于或等于@987654332 @,它只会运行一次。

之所以有效,是因为这正是我们想要的。我们不想多次交换,因为如果这样做,我们只会再次交换相同的两个值,从而导致不必要的冗余。

所以,我在想为什么我们不能在循环中省略 j-=gap,因为它似乎根本不会影响功能。包含j-=gap有什么特殊原因吗?

我错过了什么吗?

【问题讨论】:

  • 最终,gap 缩小为 1。您需要多次重复内部循环。

标签: c algorithm sorting shellsort


【解决方案1】:

查看插入排序作为参考可能会有所帮助,以了解其来源。在插入排序中,我们从左到右扫描,向后交换每个元素,直到它大于它之前的元素(或者它回到数组的开头)。该算法的伪代码如下所示:

for (int i = 1; i < n; i++) {
   for (int j = i - 1; j > 0 && A[j + 1] > A[j]; j--) {
      swap(A[j], A[j - 1]);
   }
}

外部循环覆盖数组的所有元素,表示“将每个元素放在适当的位置”。内部循环说“只要有一个在它之前的元素并且该元素大于它,就将当前元素与它之前的元素交换。”在这里,使用 +1、++、-1 和 -- 是因为我们一直在查看紧接在当前元素之前的元素。

在 shellsort 中,我们在数组上运行多次此算法,但我们不使用步长为 1。相反,我们使用称为间隙量的某个量的步长。因此,Shellsort 看起来像这样:

for (each gap size) {
   for (int i = gap; i < n; i += gap) {
      for (int j = i - gap; j > 0 && A[j + gap] > A[j]; j -= gap) {
         swap(A[j], A[j - 1]);
      }
   }
}

这个想法是每个元素都应该不断地与它之前的gap元素进行比较。如果小于这个数字,我们想将它与前面的元素交换,但需要反复比较它与前面的新元素。

例如,假设我们对这个长度为 6 的数组进行 shellsorting:

6 5 4 3 2 1

第一次执行 shellsort (gap = 3) 后,数组如下所示:

3 2 1 6 5 4

现在,假设我们使用gap = 1 进行第二次shellsort 传递。内部循环目前说“反复将每个元素向后交换到前面,直到它停止。”如果您从该循环中删除 j -= gap 步骤,则每个元素都会与它之前的元素进行比较。这将导致以下结果。在这些快照中的每一个中,克拉表示掉期正在寻找的位置:

3 2 1 6 5 4   ->   2 3 1 6 5 4
^ ^

2 3 1 6 5 4   ->   2 1 3 6 5 4
  ^ ^

2 1 3 6 5 4
    ^ ^

2 1 3 6 5 4   ->   2 1 3 5 6 4
      ^ ^

2 1 3 5 6 4   ->   2 1 3 5 4 6
        ^ ^

请注意,结果数组未排序。但是,如果我们将j -= gap 代码放回混合中,则会发生以下情况:

3 2 1 6 5 4   ->   2 3 1 6 5 4
^ ^

2 3 1 6 5 4   ->   2 1 3 6 5 4   ->   1 2 3 6 5 4
  ^ ^              ^ ^

1 2 3 6 5 4
    ^ ^

1 2 3 6 5 4   ->   1 2 3 5 6 4
      ^ ^

1 2 3 5 6 4   ->   1 2 3 5 4 6   ->   1 2 3 4 5 6
        ^ ^              ^ ^

如您所见,现在所有内容都已正确排序。

【讨论】:

    猜你喜欢
    • 2017-08-27
    • 1970-01-01
    • 2015-03-17
    • 1970-01-01
    • 1970-01-01
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多