【排序算法】希尔排序

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

对于大规模的乱序数组,插入排序很慢,因为它只会交换相邻元素,因此元素只能一点一点地从数组的一端移动到另一端。比如主键最小的元素正好在数组的另一端,那么它就得移动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次交换。

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

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

相关推荐
DoraBigHead14 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
不太可爱的大白14 分钟前
Mysql分片:一致性哈希算法
数据库·mysql·算法·哈希算法
Tiandaren4 小时前
Selenium 4 教程:自动化 WebDriver 管理与 Cookie 提取 || 用于解决chromedriver版本不匹配问题
selenium·测试工具·算法·自动化
胚芽鞘6814 小时前
关于java项目中maven的理解
java·数据库·maven
岁忧5 小时前
(LeetCode 面试经典 150 题 ) 11. 盛最多水的容器 (贪心+双指针)
java·c++·算法·leetcode·面试·go
chao_7895 小时前
二分查找篇——搜索旋转排序数组【LeetCode】两次二分查找
开发语言·数据结构·python·算法·leetcode
CJi0NG5 小时前
【自用】JavaSE--算法、正则表达式、异常
java
Hellyc6 小时前
用户查询优惠券之缓存击穿
java·redis·缓存
今天又在摸鱼6 小时前
Maven
java·maven
老马啸西风6 小时前
maven 发布到中央仓库常用脚本-02
java·maven