[算法初步]希尔排序
##1 描述
##2 场景
一群黑帮的大佬决定一起打一场牌,来小赌一把。于是他们来到一个赌场。3位大佬站在桌子的外围,发牌师站在桌子的内围。
然后发牌师开始发牌,大佬们拿到牌后,结果如下:
*[3, 7, A] [K, 6, 4][ J, 5, 2]
结果大佬们很不满意,左边的大佬说我只要小牌,右边的大佬却只想要大牌。
结果经过跟发牌师协调,这3位将每个人面前的第一张牌3,J,K丢给发牌时,让他重新排列发还。
*[3, 7, A] [J, 6, 4] [K, 5 ,2 ]
然后又将第二张也丢给发牌时排列发还。第三张也如此。结果如下:
*[3, 5, A] [J, 6, 2] [K, 7, 4]
这个虽然不是完全排序,比刚才的牌相对整齐一些,叫做基本有序了。
但是这个时候旁边两位大佬看不下了,说你们这样怎么行呢,我们俩也要玩。然后桌上的牌在不改变顺序的情况下重新分配
*[3,5][A,J][6,2][K,7][4]
左边的大佬拿的牌还不是最小,右边的大佬拿的牌也不是最大。大佬们决定继续按刚才的来,将第一张交给发牌师重新排列,然后第二张也是。
*[A,2][3,5][4,7][6,J][K]
结果还不是很满意,大佬们怒了。一个电话,又来了4个大佬。牌又分为如下:
*[A] [2] [3] [5] [4] [7] [6] [J] [K]
然后所有的大佬又将牌交给发牌师重新排列,当发牌师排列完成,桌上的牌变成有序了。
*[A] [2] [3] [4] [5] [6] [7] [J] [K]
算法描述:
设定一个增量,将相隔一个增量的内容组成一个序列优先进行排序,这样使得当前的序列变得基本有序而不是局部有序。
这样不断减小增量,直到增量为1的时候所有牌变得有序。
伪代码
input: an array a of length n with array elements numbered 0 to n − 1
inc ← round(n/2)
while inc > 0 do:
for i = inc .. n − 1 do:
temp ← a[i]
j ← i
while j ≥ inc and a[j − inc] > temp do:
a[j] ← a[j − inc]
j ← j − inc
a[j] ← temp
inc ← round(inc / 2.2)
3 go语言实现
package main
import "fmt"
/*
* [希尔]场景:
* 2 设定一个增量,将将相隔一个增量的内容组成一个序列优先进行排序。
* 7 重复步骤2,直到右边所有的牌都排序完成
*/
func ShellSort(data *[9]int) {
increment := len(data)
var i, j int
for {
//获取增值
increment = increment/3 + 1
for i = increment; i < len(data); i++ {
temp := data[i]
j = i
for ; j >= increment && data[j-increment] > temp; j = j - increment {
data[j] = data[j-increment]
}
// 插入牌到移动后牌空出的位置上,在判断出的j位置之后
data[j] = temp
}
if increment <= 1 {
break
}
}
}
/**
* @param args
*/
func main() {
data := [9]int{3, 5, 1, 7, 6, 2, 11, 13, 4}
ShellSort(&data)
for i := 0; i < len(data); i++ {
fmt.Print(data[i])
fmt.Print(",")
}
}