前端必会算法(三):插入排序

524 阅读2分钟

前言

阅读《学习JavaScript数据结构与算法(第3版)》有感
希望自己每次学习算法都能输出一篇博客,收入专栏,检查自身学习情况~ 文章有错欢迎各路大神指正,别喷,硬要喷的话,麻烦轻点,谢谢大神们~

开始

插入排序指把每次待排序元素插入到已排好的有序序列里。插入排序每次排一个数组项,以此方式构建最后的排序数组。假定第一项已经是有序序列。\

接着,它和第二项进行比较——第二项是应该待在原位还是插到第一项之前呢?这样,头两项就已正确排序,接着和第三项比较(它是该插入到第一、第二还是第三的位置呢),以此类推。

思路

比如数组 [3,5,1,4,2] image.png

  • 由上图左边第5行可看出,将 array[2]array[1] 比较,array[2] > array[1],将array[2] 插入到array[1] 前面(即 array[1] 后移了一位),1 和 5互换了个位置,数组变为[3,1,5,4,2]
  • 由上图左边第6行可看出,将插入了第一次后的数组又进行一次与上面一致的比较 array[1] > array[0],数组变为 [1,3,5,4,2],以此类推,直到最后一个元素比较完
  • 具体实现看下面注释

实现

function insertionSort(array) {
  if (array.length <= 1) return array; // 如果数组长度为1,直接返回
  var sum = 0 // 用来记录循环了多少次
  for (var i = 1; i < array.length; i++) {
    var j = i; // 以索引1为例子
    var temp = array[j]; // 存储一个需要比较的值,开始向前比较
    // 1.若temp < arr[j-1],则arr[j-1]后移(即令arr[j] = arr[j-1]);
    // 2.继续比较 arr[j-2] 与 temp,若temp < arr[j-2],则arr[j-2]后移(令arr[j-1] = arr[j-2]),
    //   若temp>arr[j-2],则arr[j-1] = temp
    while (j > 0 && array[j - 1] > temp) {
      sum++
      array[j] = array[j - 1]; // 这里可看成是将 j-1 了后移一位
      j--;
    }
    array[j] = temp;
  }
  console.log('sum: ', sum); // 6
  return array;
}
var arr = [5, 4, 3, 2, 1];
console.info(insertionSort(arr));

优化

暂无优化想法,欢迎各路大神评论

看到有掘友用二分查找法进行优化,后续对二分查找法分析后再进行补充

复杂度

排序小型数组时,此算法比选择排序和冒泡排序性能要好。相比冒泡排序和选择排序,插入排序的使用相对多一些。因为前两者是交换排序,本质上需要3次原址操作的。时间复杂度为 「O(n²)」 的算法,包含有嵌套的两个循环,这导致了二次方的复杂度

其他

# 前端算法学习-算法复杂度
# 前端必会算法(一):冒泡排序
# 前端必会算法(二):选择排序

最后

渣渣一个,欢迎各路大神多多指正,不求赞,只求监督指正