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

    本文参考资料:书籍《大话数据结构》,微信公众号:码农有道。

    希尔排序算法介绍

    希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

    简单插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,比较和移动元素均需n-1次。

    而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1。希尔排序通过这种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。然后缩小增量,到增量为1时,其实多数情况下只需微调即可,不会涉及过多的数据移动。

    所以简单的插入排序算法对基本有序或规模较小的数据比较高效,希尔排序可以说是简单插入排序的升级版,它对较大规模并且无序的数据也非常有效率。

    希尔排序详解

    首先它把较大的数据集合分割成若干个小组(逻辑上分组),然后对每一个小组分别进行插入排序,此时,插入排序所作用的数据量比较小(每一个小组),插入的效率比较高

    可以看出,他是按下标相隔距离为4分的组,也就是说把下标相差4的分到一组,比如这个例子中a[0]与a[4]是一组、a[1]与a[5]是一组...,这里的差值(距离)被称为增量

     

    每个分组进行插入排序后,各个分组就变成了有序的了(整体不一定有序)

    此时,整个数组变的部分有序了(有序程度可能不是很高)

    然后缩小增量为上个增量的一半:2,继续划分分组,此时,每个分组元素个数多了,但是,数组变的部分有序了,插入排序效率同样比较高。

    同理对每个分组进行排序(插入排序),使其每个分组各自有序。

    最后设置增量为上一个增量的一半:1,则整个数组被分为一组,此时,整个数组已经接近有序了,插入排序效率高。

    同理,对这仅有的一组数据进行排序,排序完成。

    需要注意的是:对各个组进行插入的时候并不是先对一个组进行排序完再对另一个组进行排序,而是轮流对每个组进行插入排序。

    希尔排序的代码实现

    #include<stdio.h>
    #define MAXSIZE 10    //用于排序的数组个数的最大值,可修改
    
    //定义一个用于排序的顺序表结构
    typedef struct {
        int r[MAXSIZE];
        int length;        //用于记录顺序表的长度
    }SqList;
    
    //希尔排序算法
    void ShellSort(SqList *L){
        int i , j  , temp;
        int increment = L->length;
        while(increment >= 1){
            if(L->length != 1){//如果数组的长度等于1,就不需要进行排序
                increment = increment / 2;    //在进行排序前,需要先选择一个增量
                for(i = increment ;i <= L->length; i++){//插入排序
                    if(L->r[i] < L->r[i - increment]){
                        //须将L->r[i]插入有序增量子表
                        temp = L->r[i];    //暂存在temp
                        for(j = i - increment; j >=  0 && temp < L->r[j]; j -= increment){
                            L->r[j + increment] = L->r[j];    //记录后移
                        }
                        L->r[j + increment] = temp;
                    }
                }
            }    
        }
    }

    时间复杂度和稳定性分析

    通过这段代码的剖析,相信大家有些明白,希尔排序的关键并不是随便分组后各自排序,而是将相隔某个"增值“ 的记录组成一个子序列, 实现跳跃式的移动,使得排序的效率提高。

    希尔排序的时间复杂度和增量序列(增量的集合)是相关的。

    虽然插入排序是稳定的,但是希尔排序在插入的时候是跳跃性插入的,有可能破坏稳定性,所以希尔排序并不是一种稳定的算法

  • 相关阅读:
    ORACLE修改列名与列类型
    ORACLE的显式游标与隐式游标
    ORACLE 异常错误处理
    ORACLE的强制索引
    看懂ORACLE执行计划
    ORACLE建立物化视图
    普通视图和物化视图的区别
    ORACLE 中 TRANSLATE的用法
    随手小代码——归并排序
    随手小代码——选择算法排序
  • 原文地址:https://www.cnblogs.com/yuliangbin/p/8942383.html
Copyright © 2011-2022 走看看