很久以前就实现过插入排序,基本是照着书上的标准过程实现的。这个算法的思想也很简单。以从小到大排序为例,就是从第一个元素开始,往后依次选择一个元素插入到合适的位置。算法时间复杂度为 O ( N 2 ) O(N^2) O(N2)。
例如排序这几个数字:
3
→
2
→
1
→
5
→
4
3 \rightarrow 2 \rightarrow 1 \rightarrow 5 \rightarrow 4
3→2→1→5→4
首先选择3,确定其位置 :
3
→
3 \rightarrow
3→
然后选择2,确定其位置,因为2比3小,所以应该放在3的前面:
2
→
3
→
2 \rightarrow 3 \rightarrow
2→3→
然后选择1,确定其位置,因为1比2小,所以应该放在2的前面:
1
→
2
→
3
→
1 \rightarrow 2 \rightarrow 3 \rightarrow
1→2→3→
然后选择5,确定其位置,因为5比3大,所以应该放在3的后面:
1
→
2
→
3
→
5
→
1 \rightarrow 2 \rightarrow 3 \rightarrow 5 \rightarrow
1→2→3→5→
然后选择4,确定其位置,因为4比5小,比3大,所以应该放在3和5之间,5往后挪一个位置,得到:
1
→
2
→
3
→
4
→
5
1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 5
1→2→3→4→5
实现代码:
function insertSort(numbers){
for(let i = 0; i < numbers.length; i++){
for(let j = 0; j < i; j ++){
// 如果找到一个比当前数字numbers[i]大的数字numbers[j],则:
// 1. 备份numbers[i]
// 2. 先j之后数字的往后移动一个位置
// 3. 把当前数学放到刚刚腾出的位置上
if(numbers[i] < numbers[j]){
let backup = numbers[i];
for(let k = i; k > j; k--){
numbers[k] = numbers[k - 1];
}
numbers[j] = backup;
break;
}
}
}
}
今天上了卜东波的算法课,知道了原来从分治
的角度来理解更加合适。对一个长度为
n
n
n的数组排序问题变成了先对前面长度为
n
−
1
n-1
n−1部分排序再确定最后一个元素位置的问题。实际上就是变成了递归的写法。代码如下。这种写法仅用于理解,实际使用会因为递归深度太大而导致栈溢出从而不能在实际项目使用。
/**
* 插入排序
* @param {Array} numbers 数组
* @param {number} start 排序开始位置
* @param {number} end 排序结束位置的下一位
*/
function insertSort(numbers, start, end){
if(start < end){
// 先把前面的排好
insertSort(numbers, start, end - 1);
// 再确定最后一个元素的位置
for(let j = start; j < end - 1; j++){
// 如果找到一个比当前数字numbers[end - 1]大的数字numbers[j],则:
// 1. 备份numbers[end - 1]
// 2. 先j之后数字的往后移动一个位置
// 3. 把当前数学放到刚刚腾出的位置上
let current = numbers[end - 1];
if(current < numbers[j]){
for(let k = end - 1; k > j; k--){
numbers[k] = numbers[k - 1];
}
numbers[j] = current;
break;
}
}
}
}