zoukankan      html  css  js  c++  java
  • 希尔排序

    希尔排序

    希尔排序步骤

    对于一个序列,首先将它按一个数字做间隔分组,比如我们提取第一个数字81,然后间隔5个位置,取到35,再间隔5个位置取到41,再间隔5个位置超过了数组的边界。81,35,41(上图第一行中蓝色部分),对这三个数字构成的序列做一个插入排序=》35,41,81。

    然后在上面排序后的数组的基础上,缩小间隔,这次每隔3个间隔取一个数,构成序列:35,28,75,58,95(上图第二行的蓝色部分),再做插入排序。

    最后1间隔,对所有的数做插入排序。

    会发现在最后做1间隔排序的时候,整个序列已经基本有序。这对插入排序非常友好,因为如果序列基本有序,那就意味着逆序对较少,插入排序的效率接近O(n)。

    这就是希尔排序,我们设置一个间隔序列5-3-1,逐步使序列变得有序。并且发现做完5间隔的排序后,再做3间隔排序,并不会对5间隔的排序产生影响,也就是:

    K-间隔有序的序列,在执行K-1间隔排序后,仍然是K间隔有序的。

    有一个最坏的情况:

    做8间隔排序,发现序列已经有序,无序改变;

    做4间隔排序,发现序列已经有序,无序改变;

    做2间隔排序,发现序列已经有序,无序改变;

    最后不得不做1间隔排序,即所有的元素做插入排序。

    也就是说前面的N间隔排序没有起到效果。说明:

    增量元素不互质,则小增量可能根本起不到作用。

    因此,有人研究出一些经典的增量序列:

    发现时间复杂度的证明很困难。

    Java代码实现

    public void sort(int[] arr) {
        // 定义一个增量序列
        int[] seqs = {5, 3, 1};
    
        for (int seq : seqs) {
            // 下面就是插入排序
            // 默认第一个数是有序的
            for (int i = 1; i < arr.length; i++) {
                int temp = i;
               	// 每次新进来一个数,把这个数和左边已经排好序的部分比较
                for (int j = i; j > 0; j -= seq) {// 注意,这里不是j--,而是减去一个序列数
                    // 如果新进来的数比相邻左边的数小,那就把左边的数往右挪一位
                    if (arr[j] < arr[j - 1]) {
                        arr[j] = arr[j - 1];
                        temp = j - 1;
                    }
                }
                // 找到空位,插入
                if (temp != i) {
                    arr[temp] = i;
                }
            }
        }
    }
    

    优点:

    数据量大的时候效果好,使用特定增量序列的最坏时间复杂度比简单排序O(n^2)好。

    缺点:

    不是稳定排序。

  • 相关阅读:
    kali国内更新源
    nmap教程(下)
    nmap教程(上)
    apt-get常用命令
    linux如何制作程序桌面快捷方式
    linux怎么把英文版火狐浏览器改成中文
    百度地图demo
    普元云计算-一起来DIY一个人工智能实验室吧
    普元云计算-拥抱人工智能,从机器学习开始
    普元云计算-Java开发者的PaaS指南
  • 原文地址:https://www.cnblogs.com/SimonZ/p/15518320.html
Copyright © 2011-2022 走看看