插入排序
顾名思义就是在有序数列中合适位置插入再有元素 (类似扑克牌排序)
1.插入排序从后往前比
比如:我们将第二个元素与第一个元素比较,如果比第一个小,就换顺序,同样的,假设我们当前元素是第五个元素,将依次与第四个,第三个,第二个,第一个去比较,假如比第四个元素小,但比第三个元素大的话,就将它插入到这里。所以我们循环的条件为当前元素比上一个元素小且上一个元素最小下标大于0.
2.插入排序不用第一次比较都换顺序,可将元素位置固定在部份有序数列中再进行插入。
下面我们几种方法均可实现
1. 方法1
for(let i = 1; i < arr.length; i++) { // i 从1开始
let current = arr[i]
let j = arr[i-1] // 前一个元素
while(j > 0 && current < arr[j]) { // 当前元素比上一个元素小且上一个元素最小下标大于0
arr[j+1] = arr[j] // 元素位置往后推,先不进行插入操作
j--; // 依次跟再前一个元素比,最后一次循环为有序数列中比当前元素小的元素
}
arr[j+1] = current; // 所以这里要在上一次循环中的元素下一个元素位置插入当前数
}
return arr;
比如我们当前数组为 2 3 5 4 7 6,我们比较时, 2 3 5为有序数列,我们现在要插入4
第一轮循环:arr[i]=arr[3]=current = 4, arr[j]=arr[2]=5,
条件current=arr[3]=4<arr[j]=arr[2]=5满足,
(arr[j+1]=arr[3] ) = (arr[j]=arr[2]arr[j+1]) => arr[3]=5
数组变为 2 3 5 7 6 ,剩余4,因为4>3不满足条件了,所以直接插入在这里,数组变为 2 3 4 5 7 6
2. 方法2
其实跟上个方法一样,只不过我们现在内层也使用 for 循环,并且使用 a[j]表示
for (let i = 1; i < arr.length; i++) {
let current = arr[i]
for (let j = i; j >= 0 && current > arr[j-1] ; j--) { // 当前元素大于上一个元素
arr[j] = arr[j-1] //将前一个数复制到后一个数上
}
arr[j]= current
}
3.方法3
直接使用[arr[j], arr[j+1]] = [arr[j+1], arr[j]]来再每一次比较中换顺序
// 从后往前比,所以i从1开始
for (let i = 1; i < arr.length; i++){
// arr[j]为前一个元素
for (let j = i -1; j >=0; j--) {
// 当前元素跟上一个元素相比
if (arr[j+1] < arr[j]) {
[arr[j], arr[j+1]] = [arr[j+1], arr[j]] // 也可直接换顺序
} else { // 有序数组就放弃比较,注意这里不能直接使用 else
break;
}
}
}
return arr;
附一个插入排序的讲解视频:排序算法精讲】从0到1实现插入排序,详解其中的思想并使用js代码实现