1、概述
希尔排序又称递减/缩小增量排序,是直接插入排序的一种更高效的改进版本。
希尔排序是非稳定排序。
希尔排序是把记录按一定下标的一定增量分组,对每组使用直接插入排序算法排序,随着增量的减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰巧被分成一组,算法便终止。
2、算法原理
思想:元素通过每次移动较大间隙,整个数组可以快速形成局部排序好的情况,这样会让接下来的交换变的更加l快速,因为元素之间不需要进行过多次的位置交换。
步骤:
1)首先按照增量进行分组,增量初始值=数组的长度/2 ,分完组,将组内的元素进行插入排序。
2)将1)中的增量缩小,即 当前增量 = 1)中增量/2,将1)中排序后的数组进行分组,然后再次将每个组内的数据进行插入排序。
3)再次缩小增量,即 当前增量 = 2)中增量/2,其实就是我们上一部分的插入排序,将整个数组进行插入排序,最后数组就是有序的了。
3、举例
以n = 10 的一个数组 [49, 38, 65, 97, 26, 13, 27, 49, 55, 4]为例
1)第一次增量 gap = 10/2 = 5
2)第二次增量 gap = 5/2 = 2
3)第三次增量 gap = 2/2 = 1,排序完成得到数组
4、算法实现
最外层循环负责增量的生成和缩减,里边的双重循环负责插入排序
func shellSort(_ array : inout [Int]){
var j : Int
//获取增量
var gap = array.count/2
while gap > 0 {
for i in 0..<gap{
j = i+gap
while j < array.count {
if array[j] < array[j-gap]{
let tmp = array[j]
var k = j - gap
//插入排序
while k>=0 && array[k]>tmp {
array[k+gap] = array[k]
k -= gap
}
array[k+gap] = tmp
}
j += gap
}
}
//增量减半
gap /= 2
}
}
调用:
var array7 = [49, 38, 65, 97, 26, 13, 27, 49, 55, 4]
SortSummary.shellSort(&array7)
运行结果:
//希尔
[4, 13, 26, 27, 38, 49, 49, 55, 65, 97]
5、时间复杂度
希尔排序的时间复杂度与增量(即,步长gap)的选取有关。
1)当增量为1时,希尔排序退化成了直接插入排序,时间复杂度为O(n^2),
2)Hibbard增量的希尔排序的时间复杂度为O(n^3/2)。
注:排序的具体实现代码在 SortSummary.swift 文件里 调用是在 ViewController.swift