六大排序算法(2):希尔排序

介绍

希尔排序是对直接插入排序的优化。上次总结了插入排序的性能,在被排序对象逆序有序或接近逆序时插入排序的效率最低,时间复杂度为O\left ( n^{2} \right );在被排序对象顺序有序或解决顺序时效率最高,时间复杂度为O\left ( n \right )。那是否有办法将数组变成接近有序后再用插入排序,希尔找到了这个方法,并命名为希尔排序。

步骤

  1. 选定一个小于n的整数gap作为第一增量,然后将所有距离为gap的元素分在一组。分别对每组的元素进行插入排序。
  2. 再选取一个比第一增量小的整数作为第二增量,重复步骤1。
  3. 直到增量大小被减到1,相当于整个序列分到一组,进行一次直接插入排序,完成排序。

学习参考链接

 如何选择希尔增量

最初希尔提出的第一增量按照:gap = n / 2,每次排序完增量减少一半:gap = gap / 2 ,直到gap = 1。而后来Knuth提出gap = (gap / 3) + 1, 每次排序让增量变为原来的三分之一。这两个不相上下,我们写代码时采用的是除3法。

代码

void shellSort(int* arr, unsigned int size) {
	int gap = size;
	while (gap > 1) {
		gap = gap / 3 + 1; //调整希尔增量
		for (int i = 0; i < size - gap;i++) {
			int end = i;//已排序列的结尾
			int temp = arr[end + gap];
			while (end >= 0) {
				if (arr[end] > temp) {
					arr[end + gap] = arr[end];
					end -= gap;
				}else {
					break;
				}
			 }
			arr[end+gap] = temp;
		}
	}
}

 性能

希尔排序平均效率比直接插入排序高的原因:

  • 希尔排序中待排数据每次是以增量的移动步数空出插入位置,所以效率比普通插入一次一步的移动方式要快
  • 每一次排序之后数组就会变得接近有序,插入排序的移动次数就会越来越少
  • 综上所述:希尔排序在越大的数组上更能发挥优势,因为步子迈的更大,减少插入排序的移动次数更多

 时间复杂度:

  • 平均O\left ( n^{1.3} \right )
  • 最坏O\left ( n^{2} \right ),同样为逆序情况下
  • 最好O\left ( n \right ),同样为顺序情况下

空间复杂度:O\left ( n\right )

稳定性:不稳定

所谓稳定性是指待排序的序列中有两元素相等,排序之后它们的先后顺序不变。假如为A1,A2.它们的索引分别为1,2.则排序之后A1,A2的索引仍然是1和2。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值