希尔排序(golang实现)

希尔排序是一种改进的插入排序算法,通过分组减少元素移动次数提高效率。它先用较大的步长进行排序,逐步减小步长直到1,最后进行插入排序。Golang实现的希尔排序在最坏情况下时间复杂度为O(n^2),Pratt的修改版可提升至O(n log2 n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序是基于插入排序的以下两点性质而提出改进方法的:
插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率
但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位

希尔排序通过将比较的全部元素分为几个区域来提升插入排序的性能。这样可以让一个元素可以一次性地朝最终位置前进一大步。然后算法再取越来越小的步长进行排序,算法的最后一步就是普通的插入排序,但是到了这步,需排序的数据几乎是已排好的了(此时插入排序较快)。

取自维基百科中的例子:
例如,假设有这样一组数[ 13 14 94 33 82 25 59 94 65 23 45 27 73 25 39 10 ],如果我们以步长为5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:

13 14 94 33 82
25 59 94 65 23
45 27 73 25 39
10

然后我们对每列进行排序:

10 14 73 25 23
13 27 94 33 39
25 59 94 65 82
45

將上述四行数字,依序接在一起时我们得到:[ 10 14 73 25 23 13 27 94 33 39 25 59 94 65 82 45 ].这时10已经移至正确位置了,然后再以3为步长进行排序:

10 14 73
25 23 13
27 94 33
39 25 59
94 65 82
45

排序之后变为:

10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94

最后以1步长进行排序(此时就是简单的插入排序了)。

代码实现:

package main

import "fmt"

func main() {
	arr := []int{13, 14, 94, 33, 82, 25, 59, 94, 65, 23, 45, 27, 73, 25, 39, 10}
	shellSort(arr, len(arr)/2)
	fmt.Println(arr)
}

/**
希尔排序:把切片分成n个batch,对每个batch进行插入排序;然后减小batch,再对每个batch进行插入排序;直到bathc等于1
*/
func shellSort(arr []int, batchSize int) {
	if batchSize < 1 {
		return
	}
	// k : 每个batch中的元素所在batch的index, 介于[0, batchSize)
	for k := 0; k < batchSize; k++ {
		// 用到了插入排序
		for j := 1; batchSize*j+k < len(arr); j++ { // j: 用来获取每个batch所在的第k个元素,拥有多少个batch
			for n := j; n > 0; n-- {
				pre := batchSize*(n-1) + k
				next := batchSize*n + k
				if arr[next] < arr[pre] {
					arr[next], arr[pre] = arr[pre], arr[next]
				}
			}

		}
	}
	shellSort(arr, batchSize/2)
}

原始的算法实现在最坏的情况下需要进行O(n2)的比较和交换。V. Pratt对算法进行了少量修改,可以使得性能提升至O(n log2 n)。这比最好的比较算法的O(n log n)要差一些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值