插入排序学习笔记

44 阅读1分钟

1. 取出index为1的元素,和其左边的元素比较,要是小于那么交换位置。(此时前2个元素已是从小到大排序)

2. 取出index为2的元素,和其左边的元素比较,要是小于那么交换位置,一直比较下去。直到已经排好了序。

3. 取出后面的每一个元素,重复以上步骤.

可以理解为 左边是已经排好序的,右边是未排好的。拿到右边的元素,和左边的元素有规律的比较。

20210223174254141.gif

// 比较大小
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;
  }
}