js数据结构与算法_07_插入排序

一、实现插入排序

插入排序很重要,是高级排序的基础,如希尔排序、快排等等;

选择排序的核心:局部有序,标记并取出一个元素,其左边部分是局部有序,然后从排好队的元素序列中从后向前比较,比标记元素大的,向后移动一个位置,比标记元素小,则标记元素插入其后面;这里就不用for循环了,因为你不知道要循环多少次,我们使用while循环

比如这是一个要排序的无规则数组:

let arr = [4, 8, 1, 9, 6, 7];

第一次循环时,第一个元素可以看成是局部有序,那么标记元素为8(index=1),8比4大,则标记元素插入其后:

let arr = [4, 8, 1, 9, 6, 7];

第二次循环时,标记元素移到上一个标记元素的下一位也就是1(index=2),依次对有序序列从后向前比较,1比8小,8向后移动一位:

let arr = [4, 8, 8, 9, 6, 7]; //1已经被取出了

(可能有点抽象,就是在标记1的同时,我们会用一个变量将其保存,而8向后移动一位,在代码上的表现就是array【index+1】=array【index】)

继续比较,1比4小,4向后移动一位:

let arr = [4, 4, 8, 9, 6, 7]; //1已经被取出了

已经没有可以比较的了,1就是最小的,所以1会占据4原来的位置:

let arr = [1, 4, 8, 9, 6, 7]; 

就是这样重复标记然后排序移位的过程,因为是局部有序,所以最坏的情况就是从后面一直比较到最前面,时间复杂度位O(n**2),但是从平均来说,是比较一半,所以插入排序是的效率比冒泡和选择都要强;

二、完整代码

function swap(array, m, n) {
  let temp = array[m];
  array[m] = array[n];
  array[n] = temp;
}
function selectionSort(array) {
  let length = array.length;
  for (let i = 0; i < length - 1; i++) {
    //   用于标记最小的元素
    let index = i;
    for (let j = i + 1; j < length; j++) {
      if (array[index] > array[j]) {
        index = j;
      }
    }
    if (i != index) swap(array, i, index);
  }
  return array;
}

swap函数是对交换位置的逻辑的一个抽取,方便其他排序算法使用;

内层for循环的为什么j的起始值是 i+1呢?因为自己和自己比较干嘛,肯定和下一位置比较嘛;

为什么最后要加个  if (i != index) ?因为当标记最小元素的索引等于i时,说明i位置所在的元素就是剩下元素里面最小的,故,不用交换;

二、完整代码

function insertionSort(array) {
  let length = array.length;
  for (let i = 1; i < length; i++) {
    // 取出标记元素
    let index = i;
    let temp = array[i];

    while (temp < array[index - 1] && index > 0) {
      // 向后移动一位(往覆盖一位)
      array[index] = array[index - 1];
      index--;
    }
    array[index] = temp;
  }
  return array;
}

代码量虽少,但还是要好好理解一下的;

标记位为index,比较元素为index-1;

标记元素比比较元素小,就移动位置(index--),相当于指针指向了移动位置之前的元素的所在位置;

标记元素比比较元素大,就没有移动位置的话就没有(index--),那退出while后index就是比较元素index-1的后一位;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值