1、算法介绍
希尔排序(缩小增量排序),是直接插入排序的一种改进版本,是非稳定排序算法。
(1)待排序序列长度n;
(2)选取增量d,一般d小于等于n/2,按增量d分割若干个子序列分别进行直接插入排序;
(3)缩小增量d,再分割成若干子序列分别进行直接插入排序;
(4)重复步骤3直至增量为0,整个序列最后进行一次直接插入排序;
由上可知希尔排序是根据以下两点改进直接插入排序算法的:
》直接插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
》但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;
直接插入排序等价于增量为1的希尔排序。
2、代码实现
2.1、golang
package main
import (
"fmt"
)
func main() {
slice := []int{5, 3, 12, 54, 23, 12, 6, 9, 19}
//SortInsert(slice)
//SortInsertByInc(slice, 1)
SortShell(slice)
fmt.Println(slice)
}
//直接插入排序
func SortInsert(slice []int) {
n := len(slice)
for i := 1; i < n; i++ {
for j := i; j >= 1 && slice[j-1] > slice[j]; j-- {
slice[j], slice[j-1] = slice[j-1], slice[j]
}
}
}
//直接插入排序》带增量的直接插入排序
//直接插入排序等价于增量为1的希尔排序
func SortInsertByInc(slice []int, inc int) {
n := len(slice)
for i := inc; i < n; i++ { //增量插入排序
for j := i; j >= inc && slice[j-inc] > slice[j]; j -= inc {
slice[j], slice[j-inc] = slice[j-inc], slice[j]
}
}
}
//希尔排序
func SortShell(slice []int) {
for inc := len(slice) / 2; inc > 0; inc /= 2 { //循环缩小增量
SortInsertByInc(slice, inc)
}
}
2.2、python3
# 直接插入排序
def sort_insert(arr):
n = len(arr)
for i in range(1, n):
for j in range(i, 0, -1):
if arr[j - 1] > arr[j]:
arr[j], arr[j - 1] = arr[j - 1], arr[j]
else:
break
# 按增量直接插入排序
def sort_insert_by_inc(arr, inc):
n = len(arr)
for i in range(inc, n):
for j in range(i, inc - 1, -1):
if arr[j] < arr[j - inc]:
arr[j], arr[j - inc] = arr[j - inc], arr[j]
else:
break
# 希尔排序
def sort_shell(arr):
inc = len(arr) // 2 # 选择增量
while inc > 0:
sort_insert_by_inc(arr, inc)
inc //= 2 # 缩小增量
if __name__ == '__main__':
arr = [5, 3, 12, 54, 23, 12, 6, 9, 19]
# sort_insert(arr)
# sort_insert_by_inc(arr, 1)
sort_shell(arr)
print(arr)