排序算法-05希尔排序

希尔排序

1. 算法概述

是直接插入排序算法的一种更高效的改进版本,希尔排序是非稳定排序算法。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序

2. 算法原理

希尔排序的思想是使数组中任意间隔为h(步长)的元素是有序的。这样的数组也称为h有序数组,也即一个数组是h个互相独立的有序数组交叉编制在一起组成的数组。如图所示为一个h有序数组包含了4个有序子数组。

https://github.com/bye500/image/blob/master/%E7%AE%97%E6%B3%95/%E6%8E%92%E5%BA%8F/%E5%B8%8C%E5%B0%94/%E5%AD%90%E5%BA%8F%E5%88%97.png?raw=true

上图中,假设步长为4,则使 L-M-P-T,E-H-S-S,E-L-O-X,A-E-L-R为有序,然后将这4个数组交叉编制在一起组成一个大的数组:L-E-E-A-N-H-L-E-P-S-O-L-T-S-X-R,

排序过程:

  • 先取一个步长h1<arr.length(取值正整数),把所有序号相隔h1的数组元素放一组,组内进行直接插入排序
  • 然后在取一个步长h2<h1,重复上述分组和排序操作;
  • 直至hi=1,即所有记录放进一个组中排序为止
  • 实际就是arr[0]和arr[h]比较,arr[1]和arr[h+1]比较。。。每比较完一轮后,就缩小h的值
  • 该方法实质上是一种分组插入方法

希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小,插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。

3. 动图演示

下面动图以步长为arr.length/2为例,进行演示

4. 代码实现

 @Test
public void sort() {
    int[] arr = new int[]{49, 38, 65, 97, 76, 13, 27, 49, 78, 34, 12, 64, 1};
    //设置步长,一般为数组(起始数组length >>> 1,分割数组length >>> 1 >>> 1...)长度一半
    int gap = arr.length >>> 1;
    //int gap = arr.length / x(设定步长);
    //根据步长,分割数组
    //for (; gap > 0; gap /= gap) {
    for (; gap > 0; gap >>>= 1) {
        //设置 第2个数组 起始索引 left = gap; 之后步长跨越为 left = left + gap * 循环次数
        for (int start = gap; start < arr.length; start += gap) {
            int temp = arr[start];
            //start - gap 为前一个 步长数组 相对位置的 元素
            int before = start - gap;

            boolean swap = false;
            //如果 前数据 > 后数据,则交换两者位置。依次,向前推,直至before <0 即表示该相对位置的元素已经有序
            for (; before >= 0 && arr[before] > temp; before = before - gap) {
                arr[before + gap] = arr[before];
                swap = true;
            }

            if (swap) {
                //最终 before + gap 位置会被空出,将临时元素填充进去
                arr[before + gap] = temp;
            }
        }
    }
    log.info("排序后:{}", JSON.toJSONString(arr));
}
### 希尔排序算法详解 #### 算法概述 希尔排序(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]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值