zoukankan      html  css  js  c++  java
  • 算法基础之希尔排序

    希尔排序

    希尔排序是直接插入排序的改进版本。

    因为直接插入排序对那些几乎已经排好序的数列来说,排序效率极高,达到了 O(n) 的线性复杂度,但是每次只能将数据移动一位。希尔排序创造性的可以将数据移动 n 位,然后将 n 一直缩小,缩到与直接插入排序一样为 1。

    希尔排序属于插入类排序算法。

    有一个 N 个数的数列:
    先取一个小于 N 的整数 d1,将位置是 d1 整数倍的数们分成一组,对这些数进行直接插入排序。
    接着取一个小于 d1 的整数 d2,将位置是 d2 整数倍的数们分成一组,对这些数进行直接插入排序。
    接着取一个小于 d2 的整数 d3,将位置是 d3 整数倍的数们分成一组,对这些数进行直接插入排序。
    直到取到的整数 d=1,接着使用直接插入排序。
    这是一种分组插入方法,最后一次迭代就相当于是直接插入排序,其他迭代相当于每次移动 n 个距离的直接插入排序,这些整数是两个数之间的距离,我们称它们为增量。
    我们取数列长度的一半为增量,以后每次减半,直到增量为1。
    

    复杂度

    希尔排序最坏时间复杂度为 O(n^2)。
    不同的分组增量序列,有不同的时间复杂度,但是没有人能够证明哪个序列是最好的。Hibbard 增量序列:1,3,7,···,2n−1 是被证明可广泛应用的分组序列,时间复杂度为:Θ(n^1.5)。
    希尔排序的时间复杂度大约在这个范围:O(n^1.3)~O(n^2),具体还无法用数学来严格证明它。
    希尔排序不是稳定的,因为每一轮分组,都使用了直接插入排序,但分组会跨越 n 个位置,导致两个相同的数,发现不了对方而产生了顺序变化。
    

    代码

    // 增量序列折半的希尔排序
    func ShellSort(list []int)  {
    	// 数组长度
    	n := len(list)
    	// 每次减半,直到步长为1
    	for step := n / 2;step >= 1;step /= 2{
           // 开始插入排序,每一轮的步长为step
    	   for i :=step;i <n;i+=step{
    		for j:= i - step;j >= 0;j -= step{
    			// 满足插入条件交换元素
    			if list[j+step] < list[j] {
    			  list[j],list[j + step] = list[j + step],list[j]
    			  continue
    			}
    			break
    		  }
    		}
    	}
    }
    
    // 写法二
    func ShellSort2(list []int)  {
    	// 数组长度
    	n := len(list)
    	// 进行分组,每次对半分组,直到步长为1
    	for step := n/2;step >= 1;step /= 2 {
    	  // 对每一组进行插入排序
    	  for i := step;i < n;i++ {
    		deal := list[i]
    		j := i - step
    		for ;j >= 0 && deal < list[j];j -= step {
    			list[j + step] = list[j]
    		}
    		list[j + step] = deal
    	  }
    	}
    }
    

    总结

    希尔排序还是挺绕的,首先要理解它的原理,先分组,然后通过步长进行组与组之间对应元素的比较,采用插入排序的方式。
    结合代码多敲几遍加深理解,方法二理解性更好一点,排序动态图如下:
    

    参考(感谢)

    http://www.topgoer.cn/docs/goalgorithm/goalgorithm-1cm6avl1oatp4
    https://mp.weixin.qq.com/s/4kJdzLB7qO1sES2FEW0Low
    https://interviewguide.cn/#/Doc/Knowledge/算法/算法基础/十大排序?id=希尔排序
  • 相关阅读:
    Golang的跨平台编译程序
    PySide教程:Clo“.NET研究”se 狼人:
    PyS“.NET研究”ide QtCore.Signal帮助手册 狼人:
    PySide教程:“.NET研究”第一个PySide应用 狼人:
    关“.NET研究”于Android的一些设计 狼人:
    资深设计师Tony Ventrice解析手机游戏开“.NET研究”发的四个层次 狼人:
    移动开发多平台代码共享“.NET研究” 狼人:
    关于做Andr“.NET研究”oid+J2ee系统集成开发的一点心得 狼人:
    “.NET研究”【Android开发教程】一、基础概念 狼人:
    “.NET研究”如何发布你的Android应用程序 狼人:
  • 原文地址:https://www.cnblogs.com/hzpeng/p/15029167.html
Copyright © 2011-2022 走看看