1. 取出index为1的元素,和其左边的元素比较,要是小于那么交换位置。(此时前2个元素已是从小到大排序)
2. 取出index为2的元素,和其左边的元素比较,要是小于那么交换位置,一直比较下去。直到已经排好了序。
3. 取出后面的每一个元素,重复以上步骤.
可以理解为 左边是已经排好序的,右边是未排好的。拿到右边的元素,和左边的元素有规律的比较。
// 比较大小
function cmp(v1, v2) {
return v1 - v2;
}
// 交换位置
function swap(i1, i2, array) {
let temp = array[i1];
array[i1] = array[i2];
array[i2] = temp;
}
// 实现一:
function insert1(array) {
for (let begin = 1; begin < array.length; begin++) {
let cur = begin;
while (cur > 0 && cmp(array[cur], array[cur - 1]) < 0) {
swap(cur, cur - 1, array);
cur--;
}
}
}
// 优化一:不用实时交换位置,在最后一步交换位置,较少交换次数
function insert12(array) {
for (let begin = 1; begin < array.length; begin++) {
let cur = begin;
let value = array[begin];
while (cur > 0 && cmp(value, array[cur - 1]) < 0) {
array[cur] = array[cur - 1];
cur--;
}
// 在最后替换位置
array[cur] = value;
}
}
/*
优化二: 利用二分搜索找到 index 位置元素的待插入位置
已经排好序数组的区间范围是 [0, index)
*/
function search(value, endIndex, array) {
if (array.length == 0) return -1;
let begin = 0;
let end = endIndex;
while (begin < end) {
let mid = (begin + end) >> 1;
if (value < array[mid]) {
end = mid;
} else {
begin = mid + 1;
}
}
return begin;
}
function insert3(array) {
for (let begin = 1; begin < array.length; begin++) {
let value = array[begin];
// 这里一点很重要将 begin 视为最后一个元素
let insertIndex = search(value, begin, array);
// 将 [insertIndex,begin) 往后面挪一位
for (let i = begin; i >= insertIndex; i--) {
array[i] = array[i - 1];
}
array[insertIndex] = value;
}
}