4. 进阶排序算法——希尔排序(golang)

希尔排序是一种改进的插入排序,通过设置增量序列将待排序元素分组,对每组使用插入排序,逐步减少增量直至为1,最后进行少量插入排序完成排序。文章介绍了希尔排序的思想、Golang代码实现、增量序列的选择以及时间复杂度和稳定性分析。

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


希尔排序


前言

插入排序在某些情况下,效率是很高的。

比如我们的记录本身就是基本有序的,只需要少量的插入操作。

再比如,记录少的时候,插入排序效率的优势也是很明显的。

可是现实中,哪有那么理想的情况啊[>_<]

没有环境,那我们就要自己创造啊!!!


基本有序:

所谓的基本有序就是小的关键字在前面,大的基本在后面,不大不小的基本在中间。





希尔排序的思想核心


关键词: 步长分组


我们首先根据一定的步长,将原有的记录进行分组

在分组内,使用插入排序把分组变成有序。

然后调整增量,继续对分组做插入排序处理。

直至最后步长变为1,此时整个记录已经基本有序了,再进行少量的插入操作,就可以把整个记录变成有序。



举个例子:

在这里插入图片描述




代码实现


func shellSortStep(arr []int, start int, gap int) []int {

	// 数组长度
	length := len(arr)

	// 插入排序的变种
	for i := start + gap; i < length; i += gap {

		// 备份待插入的数据
		backup := arr[i]

		// 初始化待插入位置
		j := i - gap

		// 待插入数据,小于前面的数据
		for j >= 0 && backup < arr[j] {
			// 从前往后移动
			arr[j+gap] = arr[j]
			j -= gap
		}

		arr[j+gap] = backup
	}

	return arr
}

func ShellSort(arr []int) []int {

	// 数组长度
	length := len(arr)

	// 数组为空或者只有一个元素
	if length <= 1 {
		return arr
	}

	// 步长
	gap := length / 2

	for gap > 0 {

		// 处理每个元素的步长
		for i := 0; i < gap; i++ {
			shellSortStep(arr, i, gap)
		}
		gap /= 2
	}

	return arr
}


题外话:增量怎么确定?

有人说,按照Knuth序列,应该是这样的:

 // 如果h最终为1
h = 1 

 // 则h的计算公式为,同时h不应该大于1/3,否则就比整个数组长度还要大了
h = 3*h - 1


Kunth序列版代码实现

func shellSortStep(arr []int, start int, gap int) []int {

	// 数组长度
	length := len(arr)

	// 插入排序的变种
	for i := start + gap; i < length; i += gap {

		// 备份待插入的数据
		backup := arr[i]

		// 初始化待插入位置
		j := i - gap

		// 待插入数据,小于前面的数据
		for j >= 0 && backup < arr[j] {
			// 从前往后移动
			arr[j+gap] = arr[j]
			j -= gap
		}

		arr[j+gap] = backup
	}

	return arr
}

func ShellSort(arr []int) []int {

	// 数组长度
	length := len(arr)

	// 数组为空或者只有一个元素
	if length <= 1 {
		return arr
	}

	// 步长
	gap := 1
	for gap <= length/3 {
		gap = gap*3 + 1
	}

	for gap > 0 {

		// 处理每个元素的步长
		for i := 0; i < gap; i++ {
			shellSortStep(arr, i, gap)
		}
		gap = (gap - 1) / 3
	}

	return arr
}


递减率1.3版本(梳子排序)

// 梳子排序
func ComoSort(arr []int) []int {

	// 数组长度
	length := len(arr)

	// 初始化步长
	gap := length

	for gap > 1 {

		// 递减率设定为1.3,这是经过实验证明的最快的
		gap = gap * 10 / 13

		// 收缩
		for i := 0; i+gap < length; i++ {
			if arr[i] > arr[i+gap] {
				arr[i], arr[i+gap] = arr[i+gap], arr[i]
			}
		}
	}
	return arr
}


时间复杂度

希尔排序的时间复杂度是:O(n^(1.3—2))

为什么是个区间呢?

因为时间复杂度和增量的选择有关,选择不同的增量会有不同的效果。

但不论怎么说,希尔排序的性能要好于直接排序的O(n^2)。



稳定性

由于希尔排序在排序的过程中,记录时跳跃式的移动,所以希尔排序是一种不稳定排序算法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值