我给师妹说算法_2 插入排序

Posted 一只前端小马甲

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我给师妹说算法_2 插入排序相关的知识,希望对你有一定的参考价值。

每次看师妹对着屏幕的算法题憋得满脸通红,总觉得非常可爱,大有小拳拳锤算法胸口的意思,虽然说看师妹真的很疗愈,念在她请我喝的那么多杯喜茶的份上,我打算给师妹写点东西。每篇文章先从实际问题出发,由表及里的对特定算法做一个全方位的介绍,希望师妹在师兄毕业之后的日子也能快乐A题:)

1 唠唠嗑

插入排序是一种简单的排序算法,同选择算法一样,学习它有助于我们学习其他复杂算法。为什么叫做插入排序?顾名思义,这个算法的特点就是需要不断地将数字”插入“到特定的位置,具体的位置则是插入后,从数组头到该位置的数字是有序的。

2 算法思想

  1. 首先,将数组第二个数字与第一个数字比较大小,若第二个数字小则将它插入至第一位,第一个数字往后移一位;反之不变
  2. 其次,将数组的第三个数字逐个与前面的数字比较大小,若被比较的数字相对于第三个数字大,则该数字位置后移;若该数字前没有比第三个数字大的数字,则将第三个数字插入至该位置
  3. 再次,将数组的第 i 的个数字逐个与前面的数字比较大小,若被比较的数字相对于第 i 个数字大,则该数字位置后移;若该数字前没有比第 i 个数字大的数字,则将第i个数字插入至该位置
  4. 重复步骤3的”插入“过程,直到整个数组有序

插入排序算法可视化
ps:本文中以最终结果顺序排序为例

3 代码实现(javascript版)

算法思想是对于算法的自然语言描述,现在我们通过编程语言对选择排序算法进行实现。前面我们说过插入排序的关键在于插入, 这里有两个点:找到插入位置和如何插入。

3.1 找到插入位置

假设我们拿到数组的第 i 个数字,我们直到经过之前的插入操作,i 左边的数字有序,此时我们需要把 i 位置数字向左逐个比较,找到一个比该数字小的数字x,插入至x后面位置;当数字比它小时,插入第一位。

function insertSort(nums){
//	for(let i=1; i<nums.length; i++){
//		let tmp = nums[i];
//		let insertIndex = i;

		while(
			insertIndex >= 0 &&
			nums[insertIndex-1] > tmp
		){
			insertIndex--;
		}
	}
}

3.2 如何插入

在数组中插入一个数字,为了给插入的数字腾出空间,我们需要将插入位置起到数组尾部的所有元素都向右移动一位,这个移动的过程是跟随着比较过程的,数字比 i 位置数字大,则向右移动一位。

function insertSort(nums){
//	for(let i=1; i<nums.length; i++){
//		let tmp = nums[i];
//		let insertIndex = i;

		while(
//			insertIndex >= 0 && 
			nums[insertIndex-1] > tmp
			){
				nums[insertIndex] = nums[insertIndex-1];
//				insertIndex--; 
		} 
		nums[insertIndex] = tmp;
	}
//	return nums;
}

3.3 最终版本

function insertSort(nums){
	for(let i=1; i<nums.length; i++){
		// i位置对应数字
		let tmp = nums[i];
		// 元素插入位置
		let insertIndex = i;

		while(
			insertIndex >= 0 && 
			nums[insertIndex-1] > tmp
			){
				nums[insertIndex] = nums[insertIndex-1];
				insertIndex--; 
		} 
		nums[insertIndex] = tmp;
	}
	return nums;
}

4 复杂度分析

先给结论,选择排序的时间复杂度为O(N2),空间复杂度为O(1)

首先来看时间复杂度,插入的关键在于“找到插入位置”和"插入过程“,其本质是”比较“和”移动

”比较“的操作对应

//while(
//		insertIndex >= 0 && 
		nums[insertIndex-1] > tmp
//	){

”移动“的操作对应

//while(
//		insertIndex >= 0 && 
//		nums[insertIndex-1] > tmp
//	){
		nums[insertIndex] = nums[insertIndex-1];
//		insertIndex--; 
//	}

分析可以得知

  • ”比较“次数:第一次外循环的比较次数1 + 第二次外循环的比较次数2 + 第i次外循环的比较次数i ++ n-1 = n(n-1)/2
  • ”移动“次数:第一次外循环的移动次数1 + 第二次外循环的比较次数2 + 第i次外循环的比较次数i ++ n-1 = n(n-1)/2

其次是空间复杂度,insertSort函数中,变量数量为常量

5 总结

本文介绍了一种简单的排序算法——插入排序。首先,从名字入手,提出了该算法的思路;其次,指出了算法的关键在于“找到插入位置”和“如何插入”,并用编程语言分别实现了“找到插入位置”和“插入数字”的过程,实现了该算法;最终,根据代码对算法的时间和空间复杂度进行分析,得出结论:选择排序的时间复杂度为O(N2),空间复杂度为O(1)。

以上是关于我给师妹说算法_2 插入排序的主要内容,如果未能解决你的问题,请参考以下文章

我给师妹说算法_1 选择排序

我给师妹说算法_1 选择排序

7种基本排序算法的Java实现

排序算法(3/4) 之 插入排序_md

4.2_8种常用排序算法2(插入排序:直接插入排序+希尔排序)

插入排序详解