排序算法-希尔排序

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

希尔排序步骤

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

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

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

常用的增量序列

  • 希尔增量序列:gap = n / 2 , n/4, n/8... ,其中n为原始数组的长度,这是最常用的序列,但却不是最好的。
  • Hibbard序列:(1, 3, 7, 15, ..., 2^k - 1) 公式:gap = 2^k-1, ..., 3, 1

  • Sedgewick序列:(1, 5, 19, 41, ...) 公式:gap = 9 * 4^i - 9*2^i + 1  或gap = 4^i - 3 * 2^i + 1  

代码实现

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变量)。

### 希尔排序算法详解 #### 算法概述 希尔排序(Shell Sort),亦称为递减增量排序算法,是对插入排序的一种优化版本[^1]。该算法由Donald Shell于1959年提出,并在论文“A high-speed sorting procedure”中对其进行了详细的阐述[^3]。 #### 工作原理 希尔排序通过比较相隔一定间隔的元素来工作,这些间隔逐渐减少直到变为1。当间隔为1时,希尔排序即成为普通的插入排序。这种策略使得远距离的数据可以更快地移动到接近其最终位置的地方,从而提高了整体性能[^4]。 #### 时间复杂度分析 尽管具体的渐近时间复杂度取决于所使用的间隔序列,但在最坏情况下,希尔排序的时间复杂度通常优于简单的插入排序。对于某些特定的选择间隔序列,平均情况下的表现甚至能够达到接近\( O(n \log n) \)。 #### 实现细节 以下是使用Python编写的希尔排序的具体实现: ```python def shell_sort(arr): n = len(arr) gap = n // 2 while gap > 0: for i in range(gap, n): temp = arr[i] j = i while j >= gap and arr[j - gap] > temp: arr[j] = arr[j - gap] j -= gap arr[j] = temp gap //= 2 if __name__ == "__main__": test_array = [64, 34, 25, 12, 22, 11, 90] print("原始数组:", test_array) shell_sort(test_array) print("排序后的数组:", test_array) ``` 这段代码展示了如何利用逐步缩小的间隔来进行多次部分有序化的操作,最后完成整个列表的完全排序过程[^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值