希尔排序

基本概念

希尔排序(Shell Sort)基本思想
通过设定不同的间隔(gap),将数组分组进行插入排序,然后逐步缩小间隔直至为 11,最终完成整个数组的排序。

算法实现步骤

假设数组长度为 n,算法步骤如下:

  1. 设定初始间隔 gap = n / 2
  2. 按间隔将数组分组,对每组进行插入排序。
  3. 缩小间隔 gap = gap / 2
  4. 重复步骤 2∼3,直到 gap = 1
  5. 最后对整个数组进行一次插入排序。

费曼理解

内部实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class solution:
def shellsort(self,nums:[int])->[int]:
size=len(nums)
gap=size//2
while gap>0:
for i in range(gap,size):
temp=nums[i]
j=i
while j>=gap and nums[j-gap]>temp:
nums[j]=nums[j-gap]
j-=gap
nums[j]=temp
gap//=2
return nums
def sortarray(self,nums:[int])->[int]:
return self.shellsort(nums)

复杂度分析:

指标 复杂度 说明
最佳时间复杂度 O(n)O(n) 当数组已有序时
最坏时间复杂度 O(n2)O(n^2) 使用普通间隔序列时
平均时间复杂度 O(n1.3)O(n^{1.3})~ O(n1.5)O(n^{1.5}) 取决于间隔序列选择,如果选取得当接近于 O(nlogn)O(nlog⁡n)
空间复杂度 O(1)O(1) 原地排序,只使用常数空间
稳定性 不稳定 不同组间的相等元素可能改变相对顺序
补充说明:
  • 希尔排序的时间复杂度高度依赖于间隔序列的选择。
  • 当采用常见的 gap = gap // 2 间隔序列时,排序过程大约需要 log2nlog⁡2n 趟,每一趟的操作类似于分组插入排序。
  • 每一趟的排序时间复杂度约为 O(n)O(n),但随着 gap 的减小,实际操作次数逐步减少。
  • 综合来看,希尔排序的整体时间复杂度通常介于 O(nlogn)O(nlog⁡n) 和 O(n2)O(n^2) 之间,如果间隔序列选择得当,性能可接近 O(nlogn)O(nlog⁡n)
    适用场景
  • 中等规模数据(50≤n≤1000)
  • 对插入排序的改进需求
  • 对稳定性要求不高的场景
    希尔排序是插入排序的改进版本,通过分组排序减少数据移动次数,提高排序效率。
  • 优点:比插入排序更快,空间复杂度低,适合中等规模数据
  • 缺点:时间复杂度不稳定,不稳定排序,间隔序列选择影响性能

应用场景:

  • 912排序数组
    • 问题描述:给你一个整数数组 nums,请你将该数组升序排列。
    • 解决方案:实现一遍希尔排序即可
  • 506相对名次
    • 问题描述:使用长度为 n 的数组 answer 返回获奖,其中 answer[i] 是第 i 位运动员的获奖情况。
    • 解决方案:使用希尔排序后再建立索引与值的关系