【排序算法】希尔排序

希尔排序是一种基于插入排序的快速的排序算法。

对于大规模的乱序数组,插入排序很慢,因为它只会交换相邻元素,因此元素只能一点一点地从数组的一端移动到另一端。比如主键最小的元素正好在数组的另一端,那么它就得移动N-1次。希尔排序为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序,并最终用插入排序将局部有序的数组排序。

希尔排序的思想是使数组中任意间隔为h的元素都是有序的。这样的数组被称为h有序数组。在排序时,如果h很大,就能将元素移动到很远的地方,为实现更小的h有序创造条件。用这种方法,对于任意以1为结尾的h序列,都能够将数组排序。这就是希尔排序。

实现希尔排序的一种方法是对于每个h,用插入排序将h个子数组独立的进行排序。但因为子数组是相互独立的,一个更简单的方法是在h-子数组中将每个元素将换到比它大的元素之前去。只需要在插入排序的代码中将移动距离由1改为h就可以,这样希尔排序的实现就转化为了一个类似于插入排序但使用不同增量的过程。

希尔排序更高效的原因就是它衡量了子数组的规模和有序性。排序之处,各个子数组都很短,排序之后的子数组都是部分有序的。这两种情况都很适合插入排序。子数组部分有序的程度取决于递增序列的选择。

还是以一个整数数组为例:

java 复制代码
public class Shell {
    public static void sort(int[] a)
    {
        int N=a.length;
        int h=1;
        while (h<N/3)
            h=3*h+1;
        while (h>=1)
        {
            for (int i=h;i<N;i=i+1)
            {
                for (int j=i;j>=h&&(a[j]<a[j-h]);j=j-h)
                    list_deal.exch(a,j,j-h);
                    list_deal.printArray(a);
            }
            h=h/3;
        }
    }
    public static void main(String[] args) {
        int[] a={534,745,264,864,136,967,254,745,734,269,538,265,825,158,139};
        list_deal.printArray(a);
        sort(a);
    }
}

排序过程:

java 复制代码
534 745 264 864 136 967 254 745 734 269 538 265 825 158 139 
158 745 264 864 136 967 254 745 734 269 538 265 825 534 139 
158 139 264 864 136 967 254 745 734 269 538 265 825 534 745 
136 139 264 864 158 967 254 745 734 269 538 265 825 534 745 
136 139 264 864 158 967 254 745 734 269 538 265 825 534 745 
136 139 254 864 158 967 264 745 734 269 538 265 825 534 745 
136 139 254 745 158 967 264 864 734 269 538 265 825 534 745 
136 139 254 745 158 967 264 864 734 269 538 265 825 534 745 
136 139 254 745 158 269 264 864 734 967 538 265 825 534 745 
136 139 254 745 158 269 264 864 734 967 538 265 825 534 745 
136 139 254 265 158 269 264 745 734 967 538 864 825 534 745 
136 139 254 265 158 269 264 745 734 967 538 864 825 534 745 
136 139 254 265 158 269 264 745 734 534 538 864 825 967 745 
136 139 254 265 158 269 264 745 734 534 538 864 825 967 745 
136 139 254 265 158 269 264 745 734 534 538 864 825 967 745 
136 139 254 265 158 269 264 745 734 534 538 864 825 967 745 
136 139 254 265 158 269 264 745 734 534 538 864 825 967 745 
136 139 158 254 265 269 264 745 734 534 538 864 825 967 745 
136 139 158 254 265 269 264 745 734 534 538 864 825 967 745 
136 139 158 254 264 265 269 745 734 534 538 864 825 967 745 
136 139 158 254 264 265 269 745 734 534 538 864 825 967 745 
136 139 158 254 264 265 269 734 745 534 538 864 825 967 745 
136 139 158 254 264 265 269 534 734 745 538 864 825 967 745 
136 139 158 254 264 265 269 534 538 734 745 864 825 967 745 
136 139 158 254 264 265 269 534 538 734 745 864 825 967 745 
136 139 158 254 264 265 269 534 538 734 745 825 864 967 745 
136 139 158 254 264 265 269 534 538 734 745 825 864 967 745 
136 139 158 254 264 265 269 534 538 734 745 745 825 864 967 

可以看到,总共有27次元素交换,而同样的数组用插入排序,需要63次交换。

与选择排序和插入排序形成对比的是,希尔排序也可以用于大型数组,它对任意排序的数组表现也很好。

希尔排序的另一个优点是代码量很小,且不需要使用额外的内存空间。

相关推荐
dragoooon3422 分钟前
[优选算法专题六.模拟 ——NO.40~41 外观数列、数青蛙]
数据结构·算法·leetcode
面向星辰43 分钟前
扣子开始节点和结束节点
java·服务器·前端
徐新帅44 分钟前
CCF-GESP 等级考试 2025年3月认证C++一级真题解析
算法
陌路201 小时前
S16 排序算法--堆排序
算法·排序算法
烛衔溟1 小时前
C语言算法:排序算法入门
c语言·算法·排序算法·插入排序·冒泡排序·选择排序·多关键字排序
一匹电信狗1 小时前
【C++】封装红黑树实现map和set容器(详解)
服务器·c++·算法·leetcode·小程序·stl·visual studio
.小小陈.1 小时前
数据结构5:二叉树
数据结构
Laity______1 小时前
指针(2)
c语言·开发语言·数据结构·算法
是苏浙1 小时前
零基础入门C语言之C语言实现数据结构之顺序表经典算法
c语言·开发语言·数据结构·算法
烤麻辣烫1 小时前
黑马程序员苍穹外卖(新手)Day1
java·数据库·spring boot·学习·mybatis