• 希尔排序


    希尔排序

    希尔排序步骤

    对于一个序列,首先将它按一个数字做间隔分组,比如我们提取第一个数字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)好。

    缺点:

    不是稳定排序。

  • 相关阅读:
    laravel使用ORM或者DB使用select进行查询指定字段时,可以给字段设置固定值
    sql语句左链接left join--3张表关联
    mysql将字符串转成数字
    laravelORM查询构建器查询,在排序中计算
    php 商品以元为单位设置保留两位小数
    php中根据二维数组中一维数组的某个字段进行排序
    js sort方法根据数组中对象的某一个属性值进行排序
    MySQL中查询表及索引大小的方法
    c++ const成员函数
    c++ sizeof和strlen 字符数组和字符指针
  • 原文地址:https://www.cnblogs.com/SimonZ/p/15518320.html
Copyright © 2020-2023  润新知