• 数据结构学习笔记2--希尔排序


    希尔排序比简单排序快得多,大约需要O(N×(logN)2)的时间,而且容易实现。希尔排序是基于插入排序,只是希尔排序不是比较相邻的数据,而是比较一定间隔的两个数据。

    们在选择排序算法时,基本上都可以使用希尔排序,如果有特殊要求或者算法不够快,在选择其他的排序算法。我们从插入排序的缺陷入手,看看问题:

    问题:

    插入排序思路:在标记符左边的数据是已经排序的,而右边的数据是没有排序,它有一个临时变量存储标记符所指的数据。当执行下一步是,从标记符数据项的左边第一个数据开始,依次次把左边的数据项与标记符所指的数据比较,直到找到临时变量所在的正确位置为止。

    插入排序缺陷(即比较相邻数据的缺陷):当一个很小的数据在靠右的位置时,而这里应该是较大数据坐在的位置。要把值小的数据移动到左边,需要移动和比较的次数就会几乎等于N(假如有N个数据)。若数据量很大,则排序消耗的时间就会很长,效率几乎是O(N2)。

    解决办法:

    n-增量排序

    1.通过加大排序中元素之间的间隔,在这些间隔的元素中进行插入排序。经过排序后,此时在n间隔的数据项已经是有序的。

    2.减小排序间隔,在对这些间隔的数据项进行排序。重复执行,即依次减少间隔。

    3.最后数据项间隔为1,即为插入排序。虽然此时的数据没有完全排好顺序,但是不会出现较小的数据在数据项左边的情形。

    一.图说明:以n=3为间隔

    image

    经过4次排序后,可以看到数据的位置离正确的位置相差不远,此时在通过插入排序就能够快速的对整个数据项排列了。

    二.间隔选择:

    由于最后一次排序是插入排序,所以最后一次的间隔一定为1。我们反推回去,如果以3个间隔,则

    1.倒数第二次的间隔为:1×3 + 1 = 4;

    2.倒数第三次的间隔为:4×3 + 1= 13;

    3.倒数第四次的间隔为:13×3 +1 = 40;

    ….

    代码:

    /**
         * 希尔排序实现
         * 
         * @param arr 数据项
         */
        public static void shellSort(int[] arr)
        {
            // 设置间隔初始值
            int h = 1;
    
            // 这里取3作为间隔
            while (h <= arr.length / 3)
            {
                h = h * 3 + 1;
            }
    
            while (h > 0)
            {
                for (int i = h; i < arr.length; i++)
                {
                    // 存储当前比较的数据到临时变量,即相当于插入排序中的标识对应的数据
                    int temp = arr[i];
    
                    // 赋值给j,后面对j处理
                    int j = i;
    
                    while (j > h - 1 && arr[j - h] >= temp)
                    {
                        // 移位,将小的arr[j - h]的数据移动到arr[j]的位置上
                        arr[j] = arr[j - h];
                        j = j - h;
                    }
    
                    // 将临时变量的数值赋值为arr[j],因为arr[j]的位置已经被arr[j - h]代替。
                    arr[j] = temp;
                }
    
                // 缩小h的范围
                h = (h - 1) / 3;
            }
        }

    代码单步调试过程中发现:for循环比较实际上数据比较顺序为(0,4),(1,5),(2,6),(3,7),(0,4,8),(1,5,9)。

    总结:

    希尔排序是非常实用的一种排序方法,在一般情况下使用希尔排序也能够满足大数据的要求(特殊场景除外),而且代码简单,效率比简单排序要好,是一个性价比很高的排序方法。

  • 相关阅读:
    centos 配置静态ip
    mysql常用命令
    mac 安装好mysql后密码重置
    安装Intellij Idea14/15
    freemarker 学习一 入门小例子
    获取类路径
    mysql中的int smallint 取值范围
    MySQL按照汉字的拼音排序
    Log4j 基本配置
    追加写入
  • 原文地址:https://www.cnblogs.com/winlrou/p/3502777.html
Copyright © 2020-2023  润新知