每日一题
Day1 兔子试毒 #每日一题
Day2 排序算法-插入排序 #每日一题
Day3 排序算法 #每日一题
希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。该方法因 D.L.Shell 于 1959 年提出而得名。
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止。
数组准备
默写排序算法
func arrSort(arr []int) []int {
length := len(arr)
for step := length / 2; step >= 1; step /= 2 {
for i := step; i < length; i++ {
current := arr[i]
j := i - step
for j >= 0 && arr[j] > current; j -= step {
arr[j+step] = arr[j]
}
arr[j+step] = current
}
}
return arr
}
输出
start: 1630316402432926700
排序前: [793274 498081 266786 151008 636829 243626 651548 305886 697888 831901] ... [715529 760583 152069 297222 979203 168585 95815 653064 187794 350723]
排序后: [8 20 31 33 34 40 44 49 61 69] ... [999912 999938 999939 999947 999955 999957 999964 999984 999986 999994]
end: 1630316403232122200
duration: 799195500
耗时0.79秒,果然比插入算法还要快很多
理解
刚看到希尔排序的时候感觉不是很好理解,看了很多帖子,其中这个帖子讲的比较详细
扩展
希尔算法又称“缩小增量排序”
Hibbard增量和Sedgewick增量
原始希尔算法的步长计算公式为 Dk = len(arr) / 2
Hibbard增量步长计算公式为 Dk = 2^k-1
func hbd(length int) (hibbard []int) {
for i := 1; ; i++ {
step := int(math.Pow(2, float64(i)) - 1)
if step < length {
hibbard = append(hibbard, step)
} else {
break
}
}
return
}
func arrSort(arr []int) []int {
length := len(arr)
steps := hbd(length)
// fmt.Println(steps)
sl := len(steps)
for s := sl - 1; s >= 0; s-- {
step := steps[s]
for i := step; i < length; i++ {
current := arr[i]
j := i - step
for ; j >= 0 && arr[j] > current; j -= step {
arr[j+step] = arr[j]
}
arr[j+step] = current
}
}
return arr
}
start: 1630317181790944800
排序前: [793274 498081 266786 151008 636829 243626 651548 305886 697888 831901] ... [715529 760583 152069 297222 979203 168585 95815 653064 187794 350723]
排序后: [8 20 31 33 34 40 44 49 61 69] ... [999912 999938 999939 999947 999955 999957 999964 999984 999986 999994]
end: 1630317182590263900
duration: 799319100
Sedgewick增量步长计算公式为 Dk = 9*4^k - 9*2^k + 1 || 4^k - 3*2^k + 1
func sgw1(i int) int {
return int(9*math.Pow(4, float64(i)) - 9*math.Pow(2, float64(i)) + 1)
}
func sgw2(i int) int {
return int(math.Pow(4, float64(i)) - 3*math.Pow(2, float64(i)) + 1)
}
func sgw(length int) (sedgewick []int) {
i := 0
j := 0
for len(sedgewick) == 0 || sedgewick[len(sedgewick)-1] < length {
step1 := sgw1(i)
for ; ; j++ {
step2 := sgw2(j)
if step1 > step2 {
if step2 > 0 && step2 < length {
sedgewick = append(sedgewick, step2)
}
} else {
break
}
}
if step1 < length {
sedgewick = append(sedgewick, step1)
i++
} else {
break
}
}
return
}
func arrSort(arr []int) []int {
length := len(arr)
steps := sgw(length)
// fmt.Println(steps)
sl := len(steps)
for s := sl - 1; s >= 0; s-- {
step := steps[s]
for i := step; i < length; i++ {
current := arr[i]
j := i - step
for ; j >= 0 && arr[j] > current; j -= step {
arr[j+step] = arr[j]
}
arr[j+step] = current
}
}
return arr
}
start: 1630316482425062200
排序前: [793274 498081 266786 151008 636829 243626 651548 305886 697888 831901] ... [715529 760583 152069 297222 979203 168585 95815 653064 187794 350723]
排序后: [8 20 31 33 34 40 44 49 61 69] ... [999912 999938 999939 999947 999955 999957 999964 999984 999986 999994]
end: 1630316483222124000
duration: 797061800