插入排序是一个基础排序算法,网上都说比较简单。但是我在彻底去理解它的过程和原理的时候,还是着实花了一些精力。把这个过程用一个流程图记录下来,方便自己和需要的伙伴阅读。
一、核心思想
插入排序的核心思想是,将待排数组抽象划分成两个区域,一个是有序区域,一个是无序区域。通过两层循环,逐一的将无序区域的内容,按顺序插入到有序区域。核心步骤是:
1,初始区域划分:第一个元素(index = 0)初始为有序区域,因为只有一个元素,不存在有序无序一说;从第二个元素(index = 1)往后算初始的无序区域
2,外层循环作用1:开始时,逐一的从无序区域获取待排元素,持有该元素,准备插入有序区域。
3,内层循环作用:遍历有序区域的每一个元素,为待插入元素腾挪出插入的空间,同时找到插入的位置。
4,外层循环作用2:一次外层循环结束时,此时已经找到插入位置,并且插入位置已经腾挪好了,直接将待排元素插入覆盖到该位置即可。
注意,这里一直是在同一个数组上操作,我们只是把这个数组抽象划分成了两个区域。
二、示例代码
/**
* 使用插入排序方式,将参数数组按照从小到大排列
* @param {*} arr 待排数组
*/
function insertionSort(arr){
if(arr.length <=1){
return arr;
}
// 外层循环的作用是,依次拿着每一个无序列表中的内容,准备插入到有序列表中。
// 起始的时候,就拿着数组中的第二个元素去比较。因为默认第一个是有序的。
for(let i=1; i<arr.length; i++) {
let j = i-1; // 第 i 个元素的左边是有序的, 一开始的时候,认为第1个(index = 0)的数据是有序的
const sortingValue = arr[i]; // 这是一个关键要处理的元素,等待插入到对应的位置。
console.log(`insertionSort :: outer loop, i = ${i}, j = ${j}, sortingValue = ${sortingValue}, arr = ${JSON.stringify(arr)}`);
// 这个循环是关键,核心作用是找到需要插入的位置,将第 i 个元素插入进去。
// 用左侧区域的数组的每一项跟value比较,查找插入位置 j+1
// 核心技巧是:移动元素(复制一个重复元素),类似一个冒泡过程。
for(; j>=0; j--){
if(arr[j] > sortingValue){
arr[j+1] = arr[j]; // 复制一个元素,并且通过循环移动它,此时会多出现一个重复元素,重复元素的位置就是可以插入待排数据的位置。这也是核心技巧。
console.log(`insertionSort :: inner loop, copied and moved item, i = ${i}, j = ${j}, sortingValue = ${sortingValue}, arr = ${JSON.stringify(arr)}`);
}else{
// 如果左边的这个元素已经是小的了,那么,此时的j的右边,也就是 j+1的位置就是 value应该插入的位置
console.log(`insertionSort :: inner loop, got index(${j+1}) to insert, i = ${i}, j = ${j}, sortingValue = ${sortingValue}, arr = ${JSON.stringify(arr)}`);
break;
}
}
// 将value插入找到的位置。
arr[j+1] = sortingValue;
console.log(`insertionSort :: outer loop, inserted sortingValue into(j+1) =[${j+1}], j = ${j}, sortingValue = ${sortingValue}, arr = ${JSON.stringify(arr)}`);
}
return arr;
}
const originalArray = [12,9,16,7];
const sortedArray = insertionSort([...originalArray]);
console.log(`sortedArray = ${JSON.stringify(sortedArray)}`);
以上代码的输出:
insertionSort :: outer loop, i = 1, j = 0, sortingValue = 9, arr = [12,9,16,7]
insertionSort :: inner loop, copied and moved item, i = 1, j = 0, sortingValue = 9, arr = [12,12,16,7]
insertionSort :: outer loop, inserted sortingValue into(j+1) =[0], j = -1, sortingValue = 9, arr = [9,12,16,7]
insertionSort :: outer loop, i = 2, j = 1, sortingValue = 16, arr = [9,12,16,7]
insertionSort :: inner loop, got index(2) to insert, i = 2, j = 1, sortingValue = 16, arr = [9,12,16,7]
insertionSort :: outer loop, inserted sortingValue into(j+1) =[2], j = 1, sortingValue = 16, arr = [9,12,16,7]
insertionSort :: outer loop, i = 3, j = 2, sortingValue = 7, arr = [9,12,16,7]
insertionSort :: inner loop, copied and moved item, i = 3, j = 2, sortingValue = 7, arr = [9,12,16,16]
insertionSort :: inner loop, copied and moved item, i = 3, j = 1, sortingValue = 7, arr = [9,12,12,16]
insertionSort :: inner loop, copied and moved item, i = 3, j = 0, sortingValue = 7, arr = [9,9,12,16]
insertionSort :: outer loop, inserted sortingValue into(j+1) =[0], j = -1, sortingValue = 7, arr = [7,9,12,16]
sortedArray = [7,9,12,16]
三、排序过程详解
可参看: 图解插入排序(JS版本) | ProcessOn免费在线作图,在线流程图,在线思维导图 |