从零开始学算法(三)插入排序

插入排序

代码是Javascript语言写的(几乎是伪代码)

算法介绍

插入排序(Insertion Sort)引用左老师的一句话理解:“就像是手里抓好了一副排好顺序的牌,新抓一张以后,从后往前划,一张张比较,最后在合适的位置把它插进去

算法原理

划分“手牌区”以及将待插入元素与“手牌区”里排好序的元素进行大小比较,依此向前逐个比较,待插入的元素小于比较的元素,则交换位置,完成插入后“手牌区”向后扩一,再将“手牌区”后的元素依此进行上述操作,以此类推

算法简单记忆说明

5,3,4,0,6,2
0,1,2,3,4,5 (位置)
刚开始我们认为0到0是排好序的,即数字5为我们的手牌

第一次比较插入
5,3,4,0,6,2
0,1,2,3,4,5
0位置上的数不动,看1位置上的数与0位置上的数作比较,如果小,就交换位置
3<5交换位置
3,5,4,0,6,2
0,1,2,3,4,5
随后我们的手牌区变成了3,5两张牌

第二次比较插入
3,5,4,0,6,2
0,1,2,3,4,5
0和1位置上的数不动,看2位置上的数与手牌区里的牌依此比较,如果小就交换位置
4<5交换位置
3,4,5,0,6,2
0,1,2,3,4,5
4>3不交换
随后手牌区变成了3,4,5三张牌

第三次比较插入
3,4,5,0,6,2
0,1,2,3,4,5
手牌区的数不动,看3位置上的数与手牌区里的牌依此比较,如果小就交换位置
0<5交换位置
3,4,0,5,6,2
0,1,2,3,4,5
0<4交换位置
3,0,4,5,6,2
0,1,2,3,4,5
0<3交换位置
0,3,4,5,6,2
0,1,2,3,4,5

第四次比较插入

以此类推

最终排好序:0,2,3,4,5,6

算法复杂度和稳定性

插入排序的时间复杂度是与数据状况有关的

  • 数据顺序排好为O(N)
  • 数据逆序排好为O(N2)

插入排序是稳定排序算法

算法稳定性的定义: 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的。

插入排序选择选第一个元素为有序的,后面的元素和手牌区里的元素作比较,比手牌区里元素大的就放在它后面,比它小就和它交换位置,和它相等,就放在它后面。所以插入排序是稳定的

代码实现

var Insertionarr=[5,3,4,0,6,2];
function InsertionSort(arr){
	if(arr==null||arr.length<2){return;}
	for(var i=1;i<arr.length;i++){
		for(var j=i-1;j>=0&&arr[j]>arr[j+1];j--){
			swap(arr,j,j+1);
		}
	}
	return arr;
}
function swap(arr,i,j){
	arr[i]=arr[i]^arr[j];
	arr[j]=arr[i]^arr[j];
	arr[i]=arr[i]^arr[j];
}

InsertionSort(Insertionarr);
console.log(Insertionarr);

输出结果:0,2,3,4,5,6

代码解释:
第一个for循环i相当于要插的牌,因为默认0位置的已经排好,所以i从1开始
第二个for循环,j>=0表示不越界,如果arr[j]>arr[j+1],则交换它们,之后j–则相当于开始往前走往前继续比较,直到不满足for循环条件

假设一个要插入的数字a它的位置为i,j=i-1

a
i-1 i
j j+1

很容易看出j-1之后,j+1=i-1,相当于往前移动比较

猜你喜欢

转载自blog.csdn.net/weixin_42507756/article/details/84031337