插入排序

插入排序

回想下我们在打扑克时如何对扑克进行排序的,通常我们会从左往右看,每次只考虑一张牌,把它插入合适的位置。

举个例子:

4,2,5,1,3

利用上面扑克牌排序的方法进行排序。

4:4 就一个数字,认定为有序了。

2:2比4小,把2插入到4前面,变成了2,4

5:5会和它之前的4比较下,发现5比4大,无需动了,所以就是2,4,5

1:1和它之前的5比较,1小于5,再和4比较,1比4小,再和2比较,1比2小,到头了,1比所有的数都小,所以1插到最前面变成1,2,4,5

3:类似于1的方法,最终的排序结果为1,2,3,4,5

计算机编程实现这样一个方法时,唯一的区别就是我们要为插入的那个数字腾出空间,如何腾空间?就是该数之前,比它大的数字逐个往后挪。

上例中对1进行插入时会,2,4,5往后挪动变成

_,2,4,5,3

1最后放在下划线那个位置。

我们对所有目标数据一个个进行比较,插入后,整个数据就会变得有序,这样的排序方法就成为插入排序。

插入排序的动态演示图:


下面是代码实现

void insert_sort(int nums[], int len){
	for (int i = 1; i < len; ++i){
		int j = i;
		int target_value = nums[i];
		while(j>0 && target_value < nums[j-1]){
			nums[j] = nums[j-1];
			j-=1;
		}
		nums[j] = target_value;
	}
}
不难看出我们只用了一个变量来缓存当前插入的数字,所以 空间复杂度为O(1)

考虑这样一个序列:5,4,3,2,1。我们要对它进行从小到大排序,不难发现,我们在对每次数字进行插入时,需要和它之前的所有数字进行比较,这样的序列对插入排序来说,时间复杂度是最高的,O(N2/2)

而对于随机循序的,时间复杂度大概是O(N2/4)

对于已经有序的序列:1,2,3,4,5。我们再对它进行从小到达排序时,代码中的5-8是不需要执行的。时间复杂度也就是O(N)


观察这样一个序列

2,1,4,3,6,5

如果用插入排序对它进行排序时候,需要3次插入操作,相比最开始的那个例子会发现时间复杂度明显少狠多。这样的序列有个明显的特征就是:部分有序(partially sorted)。红色数字按序排列,黑色数字按序排列 

插入排序对部分有序的数据处理时,时间复杂度会小很多。

希尔排序

希尔排序就是利用插入排序对部分有序表现很好这样一个特点。具体做法是:

1.每隔h步,对数据进行插入排序。

2.不断缩小h,重复1操作,直至h为1

h初始值根据数据量大小来定

举例

4,2,5,1,3

h取2,对4,5,3进行插入排序变成3,4,5,整个序列为3,2,4,1,5。同样对2,1进行插入排序变成1,2,整个序列为3,1,4,2,5

h取1,相当于插入排序,此时的序列是部分有序了,所以耗时会很小。

希尔排序的动态演示图:


实现代码为

void insert_sort(int nums[], int len, int h){
	for (int i = h; i < len; i+=h){
		int j = i;
		int target_value = nums[i];
		while(j-h>=0 && target_value < nums[j-h]){
			nums[j] = nums[j-h];
			j-=h;
		}
		nums[j] = target_value;
	}
}

void shell_sort(int nums[], int len){
	int h = len;
	int gap = 3;
	h /= gap;
	while(h >= 1){
		insert_sort(nums, len, h);
		h = h/gap;
	}
}

希尔排序相当于把所有元素分成几个部分来排序,先一个个地把几个小部分排好,让所有元素有个大概的顺序,最后整体上用插入排序。希尔排序的时间复杂度为O(N3/2)


参考:https://algs4.cs.princeton.edu/21elementary/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值