c语言排序算法之七(希尔排序)

发布于:2024-05-06 ⋅ 阅读:(27) ⋅ 点赞:(0)

前言

以下内容是被验证可以有效理解希尔排序,代码也较容易理解。如果你发现还有很多需要增加的,欢迎留言。

为什么要单独写排序算法这一系列,看过一些贴子普遍篇幅较长。看完还依旧云里雾里,难以直观理解原理及整个过程。代码永远是基于理解的基础上才能实现。

执行过程能动画展示需方便清晰,同时需具备单步调试,方便没理解的可以回看。

语言比较推荐c语言,高级语言库函数较多,人都有惰性思维,将自己置身于环境中训练也是至关重要。

感悟心得:初级阶段学习算法,在理解的基础上每天徒手2种算法。每种算法都是一种不同的思维方式,相信第一阶段坚持30天后会有不一样的收获。

实现原理

希尔排序(Shell Sort)是一种插入排序的改进版本,其核心思想是首先将待排序的数组按照一定的间隔分组,对每组数据进行插入排序,然后逐渐减小间隔,重复分组和排序的过程,直到间隔为1,此时整个数组被视为一个组,进行最后一次插入排序。希尔排序的增量序列选择是数学上的一个难题,但希尔最初建议的增量序列是{n/2, (n/2)/2, ..., 1},其中n是数组的长度。

希尔排序的详细过程可以概括为以下几个步骤:

  1. 初始化增量:选择一个初始增量gap,通常为数组长度的一半。如果数组长度为奇数,向下取整。

  2. 分组排序:将数组分为多个子组,每个子组包含间隔为gap的元素。对每个子组使用直接插入排序进行排序。

  3. 减小增量:减小增量gap,通常为gap/2。重复步骤2,直到增量减至1。

  4. 最终排序:当增量为1时,整个数组被视为一个组,进行最后一次直接插入排序。

希尔排序的时间复杂度分析较为困难,因为它依赖于增量序列的具体形式。在特定情况下,希尔排序的时间复杂度约为O(n^1.3),在最坏情况下可能达到O(n^2)。希尔排序的空间复杂度为O(1),因为它只需常数个额外空间来存储增量和索引。希尔排序是不稳定的排序算法,因为相同的关键字可能会在分组过程中改变它们的相对次序。

动画展示过程(Shell Sort)

Comparison Sorting Visualization

具体代码实现

#include <stdio.h>
 
void shell_sort(int arr[], int len) {
    int i, j, gap;
    for (gap = len / 2; gap > 0; gap /= 2) {
        for (i = gap; i < len; i++) {
            int temp = arr[i];
            for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {
                arr[j] = arr[j - gap];
            }
            arr[j] = temp;
        }
    }
}
 
int main() {
    int arr[] = {12, 34, 54, 2, 3, 4, 34, 56, 7, 9, 10, 12};
    int len = (int) sizeof(arr) / sizeof(*arr);
    shell_sort(arr, len);
    for (int i = 0; i < len; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
    return 0;
}

Q1:

A1: