算法篇:插入排序与希尔排序


文章最后修改时间:2020-08-30 18:07

插入排序

  • 插入排序最好情况下复杂度为   O ( N ) \ O( N)  O(N), 最坏情况下复杂度为   O ( N 2 ) \ O (N^2)  O(N2)
  • 在元素顺序与有序的顺序接近的时候比较好用。
  • 插入排序每次将一个新的数插入左边的有序数列内。
void insertionSort(int a[], int length)
{
	for (int i = 1; i < length; i++) {
		//必须用来保存,否则可能被元素右移时覆盖
		int key = a[i];
		//将左边大于a[i]的数往右移
		int j = i - 1;
		while ((j >= 0) && (a[j] > key)) {
			a[j + 1] = a[j];
			j--;
		}
		//空出来的a[j+1]就是a[i]应该放的位置
		a[j + 1] = key;
	}
}

可以写为

void insertionSort(int a[], int length)
{
	for (int i = 1; i < length; i++) {
		insert(a, i, a[i]);
	}
}

插入排序的优点和劣势

  插入排序时间复杂度为 O ( n 2 ) O(n^2) O(n2),但其常数很小,适合小数组的排序,并且排序是稳定的,相等的数,排序前和排序后的前后位置不变。
  因为其常数较小,在归并排序中,小数组的排序用插入排序来替代能够加速不少。
  当数组较大时,插入排序其 O ( n 2 ) O(n^2) O(n2)复杂度的劣势就愈发的明显。当然,肯定比冒泡排序优。因为冒泡排序的交换操作比插入排序的移动操作要慢得多。
  插入排序适合逆序对少,小数组的情况。

希尔排序

为插入排序创造条件

  在数据量大的时候,插入排序就显得很吃力了,其时间复杂度是 O ( n 2 ) O(n^2) O(n2)的。插入排序适合的是小数组、逆序对少的情况。
  那么,面对一个大数组,能不能为插入排序创建出这两个条件呢?这就是希尔排序
  希尔排序通过对大数组进行分组,化整为零,然后对每一组进行插入排序,为插入排序创造了小数组的条件
  每一组一开始只有几个元素,并且对每一组都进行了插入排序。组内元素是有序了,但是整体还是很乱的。所以后面逐渐把分组减少,使每一组的元素数量更多。
  在分组减少时,因为前面已经进行小组内的插入排序,使得元素已经相对有序,这就为后面的插入排序创造了逆序对相对较少的条件。
  所以,通过主动为插入排序创造小数组、逆序对少这两个条件,使得虽然经过了N次的插入排序后,最后一次也进行了一次完整的插入排序,但是最后的结果是时间复杂度降到了 O ( n 1.5 ) O(n^{1.5}) O(n1.5)以下,下界为 O ( n log ⁡ n ) O(n \log n) O(nlogn),为最早突破 O ( n 2 ) O(n^2) O(n2)复杂度的排序算法之一。
  希尔排序的时间复杂度受增量序列影响,取不同的增量序列,得到的时间复杂度不同,而最常用的是 2 , 4 , 8 , . . . , 2 n 2, 4, 8,... ,2^n 248...2n的序列,这不是最快的增量序列,但是写法比较简单。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依稀_yixy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值