zoukankan      html  css  js  c++  java
  • 【DS】排序算法之希尔排序(Shell Sort)

    一、算法思想

    希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
    希尔排序是基于插入排序的以下两点性质而提出改进方法的:
    1)插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率;
    2)插入排序一般来说是低效的, 因为插入排序每次只能将数据移动一位;

    我们将数组中两个元素之间的距离称为Gap,相邻元素之间的Gap自然是1,很明显的,插入排序的算法在调节元素的时候,Gap是1,这就造成了上面讲的低效的原因2)。因此希尔排序的思想如下:

    1)假设序列的元素个数是n,选取一个初始Gap的d(d<n);

    2)将序列中元素之间距离(即Gap)为d的元素分为一组,在每组之间直接进行插入排序;

    3)全部完成以后,缩小Gap至d1(d1<d),然后继续2)直到Gap为1;

    常见的Gap序列如下:

    1)希尔原本的Gap:N/2、N/4、...1(反复除以2)
    2)Hibbard的Gap:1、3、7、...、2k-1(k表示第几个gap)
    3)Knuth的Gap: 1、4、13、...、(3k - 1) / 2(k表示第几个gap)
    4)Sedgewick的Gap: 1、5、19、41、109、...

    二、算法示意图

    如图所示,展示了分组和排序的过程。第一行是分组的过程,总共有8个元素,Gap为8/2=4,标记为相同颜色的元素为一组。第二行是同一组元素经过插入排序后形成的样子,可以看到,蓝色和灰色组元素进行了交换。第三行是Gap缩小为4/2=2的分组,相同颜色元素为一组,第四行是同组元素经过插入排序后形成的序列,可以看到每一组都是有序的。第五行是Gap缩小为2/2=1的分组,即整个数列为一个组,直接进行插入排序,这里就和插入排序完全一样了。

    注意到第五行的时候,序列已经基本有序了,靠近插入排序的最优情况,所以插入排序的效率极高。

    三、Java代码

     1 //@wiki
     2 public class ShellSort extends Sort {
     3     public static void sort(int array[]) {
     4         int length = array.length;
     5         int temp = 0;
     6         for (int gap = length / 2; gap >= 1; gap = gap / 2)
     7             for (int i = gap; i < length; i++)
     8                 for (int j = i; j >= gap && array[j] < array[j - gap]; j -= gap) {
     9                     temp = array[j];
    10                     array[j] = array[j - gap];
    11                     array[j - gap] = temp;
    12                 }
    13     }
    14 }

    这段代码看上去比较复杂,因为嵌套着三层for循环,另外代码的想法和上面示意描述的并不一致,因此总是会比较难理解。

    示意中讲:按照每一组进行插入排序,很容易让人想到一组组的去执行插入排序,然后一起再进行下一步。代码不是这样的,代码是所有组同时进行的,第7行可以看到,每次遍历都是从gap开始遍历到数列最后,然后对每一个元素进行往前进行插入排序,不过这次不是和前一个相邻元素作比较,而是和j-gap作比较,很容易发现,这其实是在元素所在组进行插入排序。

    四、算法复杂度

    其算法复杂度至今没有一个确定的解,其复杂度依赖于其Gap序列,范围Ο(n^1.5) ~ Ο(n^2)。而最好的情况则是序列初始状态就是顺序排列,此时算法的复杂度是O(n)。平均复杂度则为:Ο(n^5/4)。

    空间复杂度非常容易,由代码可以看出来,只需要一个位置temp用于交换即可,因此是O(1)。

  • 相关阅读:
    vue-cli生成的重要代码详解
    vuex初探
    vue-router笔记
    新技术的学习
    图片优化方法(有时间看看)
    关于老教授之家项目的思考 && 中国互联网+大赛培训
    If you are tired...
    微信公众平台开发初探
    winscp介绍与使用
    获取当前服务器信息
  • 原文地址:https://www.cnblogs.com/lqminn/p/3650033.html
Copyright © 2011-2022 走看看