插入排序与希尔排序(c++)

1. 插入排序

直接上图
插入排序与希尔排序(c++)_第1张图片

说明
1.黑色竖线将数据(data)分割为两个部分,对竖线左边进行排序
2.蓝色为已近排序的元素,红色没有排序

1.1插入排序算法流程

第一次排序: j=1, i =0;.其实就两个元素,比较一下,data[j] < data[i]. 交换二者
第二次排序:前两个元素已经有序。扩张这个有序序列.于是我们需要找到第 i 个元素应该放在哪里?
这里我们将i以此向前比较,发现,它比最大的23都打,好吧,那就放在23后面不动吧。
第三次排序:还是找 i 个元素12应该放在哪里?
首先我们应该把12用一个temp变量保存下来
然后,发现24比12大,那就把24往后挪到12的位置,然后在依次把14 -->24, 23–>14。最后,把12放到停下的位置。

1.2插入排序代码

void insert_sort(int *data, int length) {
	int i, j;
	for (i = 1; i < length; i++) //i依次往后遍历
	{
		int tmp = data[i];
		for ( j = i-1; j>=0; j--)//j 表示 i 前一个元素
		{
			if(data[j]>tmp){
				//如果j个元素已经比前一个元素大,说明应该插入到这个元素后面,因为前面的元素会更小
				break;
			}
			//往后挪动
			data[j + 1] = data[j];
		}
		//把temp的值,放到j+1个位置
		data[j + 1] = tmp;
	}
}

2.希尔排序

插入排序与希尔排序(c++)_第2张图片

2.1原理

希尔排序可以理解为插入排序的升级版,插入排序是相邻位置比较,希尔排序 跨元素比较,如上图中的,开始 data[0] 和 data[0+gap] 位置的元素比较。 即data[i] 与 data[i+gap]比较。i依次递增。
希尔排序其实是做0, 0+gap, 1+ gap, 2+gap, 3+gap…位置的插入排序。一轮结束过后, gap 除以2. 直到gap为1.
(gap为1, 就是插入排序啦。相邻位置挨个比较,达到全局有序)。
总结一下

  1. 先对0,0+gap,1+gap,3+gap 间隔gap个元素做插入排序。
  2. gap = gap/2;
  3. while(gap>=1)

2.2代码

void shell_sort(int *data, int length) {
	int gap = 0;
	int i = 0, j = 0;
	for (gap  = length/2;  gap>=1; gap = gap/2)
	{
		// 当 gap =1 的时候,就是插入排序。
		for ( i = gap; i < length; i++)
		{
			int tmp = data[i];
			for (j = i-gap;  j>=0; j=j-gap )
			{
				if(data[j]>tmp) break;
				data[j + gap] = data[j];
			}
			data[j + gap] = tmp;
		}
	}
}

时间复杂度:插入排序 O(nn)最好的情况O(n) 最坏情况(nn)
希尔排序 O(n^1.3) 最好的情况O(n) 最坏的情况(n*n)
空间复杂度:都是O(1)
稳定性: 插入排序是稳定的,希尔排序不稳定。
啥是稳定性?
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。(摘自百度百科)
插入排序与希尔排序(c++)_第3张图片

我们以希尔排序为例,假设这是一个排序的中间状态。 我们可以发现 在这一个状态下, 9 是排在 16前面的,但是在下一个状态,9 排在了 16 后面。那原本有序的 变成了 逆序对。可以看出希尔排序是不稳定的。同样的,我们看插入排序
在这里插入图片描述
12 不管怎么移动, 所有元素的相对大小位置都不会改变,这就说明,插入排序是稳定的。

排序算法的稳定性,应该具体情况具体讨论,不可一概而论。(摘自百度百科)
一般稳定的排序算法有:
而基数排序、冒泡排序、直接插入排序、折半插入排序、归并排序是稳定的排序算法。

你可能感兴趣的:(数据结构,排序算法,插入排序,数据结构)