排序算法-希尔排序

希尔排序是插入排序的改进版 ,通过将原始数组分成多个子序列进行间隔插入排序 ,逐步缩小间隔直至为1,最终完成整体排序。它也被称为缩小增量排序。

希尔排序步骤

  1. 选择增量序列(Gap Sequence) :确定一个递减的间隔序列(如 n/2, n/4, ..., 1)。

  2. 分组插入排序 :对每个间隔 gap,将数组分成 gap 个子序列,分别进行插入排序。

  3. 逐步缩小间隔 :重复上述过程,直到 gap = 1,此时数组基本有序,最后进行一次标准插入排序。

常用的增量序列

  • 希尔增量序列: ,其中n为原始数组的长度,这是最常用的序列,但却不是最好的。

  • Hibbard序列:(1, 3, 7, 15, ..., 2^k - 1) 公式:

  • Sedgewick序列:(1, 5, 19, 41, ...) 公式: 或

代码实现

java 复制代码
package Sort;

public class ShellSort {
    public static void main(String[] args) {
        int[] res = getShellSort(new int[]{4,8,6,9,2,5,3,1,7});
        for (int i = 0; i < res.length; i++) {
            System.out.print(res[i]+" ");
        }
    }
    public static int[] getShellSort(int[] nums){
        int len = nums.length;
        int currentNum;
        //按增量分组后,每个分组中
        //gap指用来分组的增量,会依次递减,直到gap=1,一般gap递减可使用/2来实现
        int gap = len / 2;
        while (gap > 0){
            // 对每个子序列进行插入排序
            for (int i = gap; i < len; i++) {
                currentNum = nums[i];
                //组内已被排序数据的索引
                int preIndex = i - gap;
                //在组内已被排序过数据中倒序寻找合适位置,如果当前待排序数据更小
                //则将比较的数据在组内后移
                //插入排序逻辑(间隔为 gap)
                while (preIndex>=0 && currentNum < nums[preIndex]){
                    nums[preIndex + gap] = nums[preIndex];
                    preIndex -= gap;
                }
                //循环结束,说明已经找到当前待排序数据的合适位置,进行插入。
                nums[preIndex + gap] = currentNum;
            }
            gap /= 2;
        }
        return nums;
    }
}
时间复杂度
  • 最坏情况:取决于增量序列(Gap Sequence)。

    • Shell 原始序列(n/2, n/4, ..., 1) :最坏时间复杂度为 O(n²)。

    • Hibbard 序列(1, 3, 7, 15, ..., 2^k - 1) :最坏时间复杂度为 O(n^(3/2))。

    • Sedgewick 序列(1, 5, 19, 41, ...) :最坏时间复杂度为 O(n^(4/3))。

  • 最好情况 :序列已经基本有序,此时希尔排序接近 O(n log n)(取决于增量序列)。

  • 平均情况:

    • Shell 原始序列 :平均时间复杂度 O(n^(3/2)) ~ O(n²)。

    • 优化增量序列(如 Sedgewick) :平均时间复杂度 O(n log n) ~ O(n^(4/3))。

空间复杂度
  • O(1)(原地排序),仅需常数级额外空间(如 currentNum变量)。
相关推荐
怕浪猫2 小时前
GEO 优化到底是什么?AI时代内容创作者必须懂的新技能
算法·面试·github
朝朝辞暮i4 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
Evand J4 小时前
【MATLAB例程】三维RRT+APF避障路径规划与到达角(AOA)定位算法|三维路径优化与定位仿真例程
算法·matlab·路径规划·代码·定位·rrt·aoa
leikooo4 小时前
用餐厅和盘子理解栈和堆
java·数据结构·链表·rust
weixin_307779135 小时前
有限产能智能排产与动态重排智能体:从需求解构到技术实现
开发语言·人工智能·算法·架构
Ivanqhz5 小时前
激活函数在 Transformer 中的作用及各种变体简述
java·linux·数据库·人工智能·深度学习
朝朝辞暮i6 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法
沙漠之主6 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
朝朝辞暮i6 小时前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
FPGA小徐6 小时前
PA1 基础设施(2)深度解析:NEMU 中 ITRACE、MTRACE、FTRACE、IRINGBUF、ETRACE、DIFFTEST 全解析
java·服务器·网络