了解希尔排序算法

    在本教程中,您将学习希尔排序的工作方式。此外,您还将找到使用C语言的示例。
    希尔排序是一种算法,该算法首先对彼此分开的元素进行排序,然后依次缩短要排序的元素之间的间隔。它是插入排序的一个通用版本。
    在希尔排序中,按特定间隔对元素进行排序。元素之间的间隔根据使用的顺序逐渐减小。希尔排序的性能取决于给定输入数组使用的序列类型。
    使用的一些最佳序列是:

  • 希尔原始序列:N/2 , N/4 , …, 1
  • Knuth增量:1, 4, 13, …, (3k – 1) / 2
  • Sedgewick增量:1, 8, 23, 77, 281, 1073, 4193, 16577…4j+1+ 3·2j+ 1
  • Hibbard增量:1, 3, 7, 15, 31, 63, 127, 255, 511…
  • Papernov和Stasevich增量:1, 3, 5, 9, 17, 33, 65,…
  • Pratt:1, 2, 3, 4, 6, 9, 8, 12, 18, 27, 16, 24, 36, 54, 81…
希尔排序如何工作?
  1. 假设我们需要对以下数组进行排序。
    在这里插入图片描述
  2. 在算法中,我们使用希尔的原始序列(N/2,N/4,…1)作为间隔。
    在第一个循环中,如果数组大小为 N = 8,则对间隔为N/2 = 4的元素进行比较并交换(如果它们不按顺序排列)。
    a. 将第0个元素与第4个元素进行比较。
    b. 如果第0个元素大于第4个元素,则第4个元素首先存储在temp变量中,第0个元素(即较大的元素)存储在第4个位置,而temp中存储的元素存储在第0个位置。
    在这里插入图片描述
        对于所有剩余的元素,此过程将继续进行。
    在这里插入图片描述
  3. 在第二个循环中,取N/4=8/4=2的间隔,并再次对位于这些间隔处的元素进行排序。
    在这里插入图片描述
        在这一点上你可能会感到困惑。
    在这里插入图片描述
        第4位和第2位的元素被比较,第2位和第0位的元素也进行了比较。数组中当前间隔的所有元素都被比较。
  4. 对剩余元素也进行相同的处理。
    在这里插入图片描述
  5. 最后,当间隔为N/8=8/8=1时,对间隔为1的数组元素进行排序。数组现在已完成排序。
    在这里插入图片描述

注:
原文第二次排序的图例有误。
第一次间隔为4,排序之后数组为:

5 6 3 1 9 8 4 7

正确。
第二次间隔为2,分别将5,3,9,4和3,4,5,9排序,排序之后的数组为:

3 1 4 6 5 7 9 8

第三次间隔为1,排序之后的数组为:

1 3 4 5 6 7 8 9
希尔排序算法伪代码
shellSort(array, size)
  for interval i <- size/2n down to 1
    for each interval "i" in array
        sort all the elements at interval "i"
end shellSort
C示例
// Shell Sort in C programming

#include <stdio.h>

// Shell sort
void shellSort(int array[], int n) {
  // Rearrange elements at each n/2, n/4, n/8, ... intervals
  for (int interval = n / 2; interval > 0; interval /= 2) {
    for (int i = interval; i < n; i += 1) {
      int temp = array[i];
      int j;
      for (j = i; j >= interval && array[j - interval] > temp; j -= interval) {
        array[j] = array[j - interval];
      }
      array[j] = temp;
    }
  }
}

// Print an array
void printArray(int array[], int size) {
  for (int i = 0; i < size; ++i) {
    printf("%d  ", array[i]);
  }
  printf("\n");
}

// Driver code
int main() {
  int data[] = {9, 8, 3, 7, 5, 6, 4, 1};
  int size = sizeof(data) / sizeof(data[0]);
  shellSort(data, size);
  printf("Sorted array: \n");
  printArray(data, size);
}
复杂度

    希尔排序是一种不稳定的排序算法,因为该算法不检查间隔之间的元素。
    时间复杂度

  • 最坏情况复杂度:小于或等于O( n 2 n^2 n2)
        根据Poonen定理,希尔排序的最坏情况复杂度为 Θ ( N l o g N ) 2 / ( l o g l o g N ) 2 ) Θ(Nlog N)^2/(log log N)^2) Θ(NlogN)2/(loglogN)2) Θ ( N l o g N ) 2 / l o g l o g N ) Θ(Nlog N)^2/log log N) Θ(NlogN)2/loglogN) Θ ( N ( l o g N ) 2 ) Θ(N(log N)^2) Θ(N(logN)2) 或介于两者之间。
  • 最佳情况复杂度:O(n*log n)
        当数组已经排序时,每个间隔(或增量)的比较总数等于数组的大小。
  • 平均情况复杂度:O(n*log n)
        大约是 O ( n 1.25 ) O(n^{1.25}) O(n1.25)

    复杂度取决于所选的间隔。对于选择的不同增量序列,上述复杂度不同。最佳的增量序列未知。
    空间复杂度:
    希尔排序的空间复杂度为O(1)。

希尔排序的应用

    在以下情况下使用希尔排序:

  • 调用堆栈是日常开销。uClibc库使用这种排序。
  • 递归超出限制。bzip2压缩器使用它。
  • 当相邻元素相距较远时,插入排序的性能不好。希尔排序有助于缩短相邻元素之间的距离。因此,要执行的交换的数量将更少。
参考文档

[1]Parewa Labs Pvt. Ltd.Shell Sort Algorithm[EB/OL].https://www.programiz.com/dsa/shell-sort,2020-01-01.
[2]Baidu.希尔排序[EB/OL].https://baike.baidu.com/item/希尔排序,2020-11-18.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值