希尔排序和插入排序很相似,有点像插入排序的升级版本。

    希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,同时该算法是冲破O(n2)的第一批算法之一

    希尔排序也是一种插入排序算法,只不过在插入排序上突破了结界,达到了另一种顶峰的存在,这种顶峰使得时间复杂度变成「O(nLogn)~O(n^2)」。
    假设我们需要给下面的数据进行排序
    C语言希尔排序 - 图1
    结合之前的文章,我们知道两个数据的插入排序就是比较两个数据的大小,然后进行排列。

    希尔排序是通过分组+插入

    **首先我们排序的数量是 8 个,我们需要把数据分成 8/2 = 4组。


    如下图
    C语言希尔排序 - 图2
    对上面4组的数据进行
    插入排序后得到**
    C语言希尔排序 - 图3
    然后再继续分组 8➗2➗2 = 2 分成 2组
    C语言希尔排序 - 图4
    这两组数据再进行插入排序

    如下图
    C语言希尔排序 - 图5
    这样之后,整个数据的排序差不多完成

    我们在这个基础上再对整个队列执行一次插入排序,就会完成了整个队列的排序,因为之前已经对数据进行过排序,再进行插入排序的时候,效率会明显得到提升。
    C语言希尔排序 - 图6
    整个过程可以观看动态图片
    C语言希尔排序 - 图7
    代码实现看看

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. int shell_sort(int arr[],int n)
    5. {
    6. register int i, j, tmp;
    7. int step;
    8. for(step = n/2; step > 0;step /= 2)/*增量步长*/
    9. {
    10. /*step = 4 2 1*/
    11. for(i = step; i < n; i++)
    12. {
    13. tmp = arr[i];
    14. j = i - step;
    15. for(;j >= 0 && tmp < arr[j];)
    16. {
    17. arr[j + step] = arr[j];
    18. j -= step;
    19. }
    20. arr[j + step] = tmp;
    21. }
    22. }
    23. }
    24. #define LENGTH 8
    25. int main( int argc, int *argv[])
    26. {
    27. int i;
    28. int arr[LENGTH] = {6,5,3,1,8,7,2,4};
    29. for(i=0;i<LENGTH;i++)
    30. printf("%d ",arr[i]);printf("\n");
    31. shell_sort(arr,LENGTH);
    32. for(i = 0;i < LENGTH;i++)
    33. printf("%d ", arr[i]);printf("\n");
    34. }

    代码输出

    1. 6 5 3 1 8 7 2 4
    2. 1 2 3 4 5 6 7 8

    代码图片解析

    步长等于4的时候,先进行第一次插入排序

    C语言希尔排序 - 图8
    步长等于2的时候,先进行第二次插入排序

    C语言希尔排序 - 图9
    步长等于1的时候,先进行第三次插入排序
    具体过程可以查看插入排序的文章

    C语言希尔排序 - 图10
    最后一次进行插入排序之后,就会得到排序完成后的数列
    C语言希尔排序 - 图11