希尔排序 python

希尔排序是一种改进的插入排序,通过设置间隔序列来加快排序速度。在排序过程中,间隔会逐渐减小,最终达到直接插入排序。文章通过图解和代码展示了希尔排序的过程,指出当间隔为1时,实际上执行的是插入排序。
摘要由CSDN通过智能技术生成

希尔排序(python)

希尔排序

希尔排序这个名字,来源于它的发明者希尔,也称作“缩小增量排序”,是插入排序的一种更高效的改进版本。

我们知道,插入排序对于大规模的乱序数组的时候效率是比较慢的,因为它每次只能将数据移动一位,希尔排序为了加快插入的速度,让数据移动的时候可以实现跳跃移动,节省了一部分的时间开支。
在这里插入图片描述

图解希尔排序

待排序数组 10 个数据:
在这里插入图片描述

假设计算出的排序区间为 4 ,那么我们第一次比较应该是用第 5 个数据与第 1 个数据相比较。

在这里插入图片描述

调换后的数据为[ 7,2,5,9,8,10,1,15,12,3 ],然后指针右移,第 6 个数据与第 2 个数据相比较。

在这里插入图片描述

指针右移,继续比较。

在这里插入图片描述

如果交换数据后,发现减去区间得到的位置还存在数据,那么继续比较,比如下面这张图,12 和 8 相比较,原地不动后,指针从 12 跳到 8 身上,继续减去区间发现前面还有一个下标为 0 的数据 7 ,那么 8 和 7 相比较。

在这里插入图片描述
比较完之后的效果是 7,8,12 三个数为有序排列。

在这里插入图片描述

当最后一个元素比较完之后,我们会发现大部分值比较大的数据都似乎调整到数组的中后部分了。

假设整个数组比较长的话,比如有 100 个数据,那么我们的区间肯定是四五十,调整后区间再缩小成一二十还会重新调整一轮,直到最后区间缩小为 1,就是真正的排序来了。

在这里插入图片描述

指针右移,继续比较:

在这里插入图片描述

重复步骤,即可完成排序,重复的图就不多画了。

我们可以发现,当区间为 1 的时候,它使用的排序方式就是插入排序。

代码实现

# python
class Sort():
    def shell_sort(self, data):
        length = len(data)
    gap <span class="token operator">=</span> <span class="token number">1</span>
    <span class="token keyword">while</span> gap <span class="token operator">&lt;</span> length<span class="token punctuation">:</span>
        gap <span class="token operator">=</span> gap <span class="token operator">*</span> <span class="token number">3</span> <span class="token operator">+</span> <span class="token number">1</span>

    <span class="token comment"># 第一层循环是改变gap的值对列表进行分组</span>
    <span class="token keyword">while</span> gap <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">:</span>
        <span class="token keyword">for</span> i <span class="token keyword">in</span> <span class="token builtin">range</span><span class="token punctuation">(</span>gap<span class="token punctuation">,</span> length<span class="token punctuation">)</span><span class="token punctuation">:</span>
            value <span class="token operator">=</span> data<span class="token punctuation">[</span>i<span class="token punctuation">]</span>
            j <span class="token operator">=</span> i <span class="token operator">-</span> gap

            <span class="token keyword">while</span> j <span class="token operator">&gt;=</span> <span class="token number">0</span> <span class="token operator">and</span> data<span class="token punctuation">[</span>j<span class="token punctuation">]</span> <span class="token operator">&gt;</span> value<span class="token punctuation">:</span>
                data<span class="token punctuation">[</span>j<span class="token operator">+</span>gap<span class="token punctuation">]</span> <span class="token operator">=</span> data<span class="token punctuation">[</span>j<span class="token punctuation">]</span>
                j <span class="token operator">-=</span> gap

            data<span class="token punctuation">[</span>j<span class="token operator">+</span>gap<span class="token punctuation">]</span> <span class="token operator">=</span> value

        gap <span class="token operator">=</span> gap <span class="token operator">//</span> <span class="token number">3</span>

    <span class="token keyword">return</span> data
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
// java
public static void sort(int[] arr) {
    int length = arr.length;
    //区间
    int gap = 1;
    while (gap < length) {
        gap = gap * 3 + 1;
    }
    while (gap > 0) {
        for (int i = gap; i < length; i++) {
            int tmp = arr[i];
            int j = i - gap;
            //跨区间排序
            while (j >= 0 && arr[j] > tmp) {
                arr[j + gap] = arr[j];
                j -= gap;
            }
            arr[j + gap] = tmp;
        }
        gap = gap / 3;
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

可能你会问为什么区间要以 gap = gap*3 + 1 去计算,其实最优的区间计算方法是没有答案的,这是一个长期未解决的问题,不过差不多都会取在二分之一到三分之一附近。

                                </div>
            <link href="https://csdnimg.cn/release/phoenix/mdeditor/markdown_views-e44c3c0e64.css" rel="stylesheet">
                </div>
</article>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值