本系列的文章列表和相关说明,请查看序言。具体列表以下:
【一块儿学习排序算法】0 序言
【一块儿学习排序算法】1 算法特性及大O记法
【一块儿学习排序算法】2 冒泡排序
【一块儿学习排序算法】3 选择排序javascript
也能够直接到github上查看完整的文章和源码!html
本篇为此系列第四篇。java
先看看Wikipedia的定义:git
Insertion sort algorithm iterates, consuming one input element each repetition, and growing a sorted output list. Each iteration removes one element from the input data, finds the location it belongs within the sorted list, and inserts it there. It repeats until no input elements remain.github
因此插入排序的思路就是:算法
能够经过动画演示理解, 如下网上找的两个动画。若是你想操做不一样的参数来演示,能够上这个网站visualgo.net动手试试。数组
关于代码,README中代码只有实现算法的函数,具体运行的代码,请查看该目录下的文件。bash
代码以下:数据结构
const insertSort = (array) => {
// 不修改原数组
const originValues = array.slice();
// 初始将第一个元素指定为有序子列,从第2个元素开始插入,直到n-1元素
for (let i = 1; i < originValues.length; i++) {
const currentValue = originValues[i];
// 标记插入有序子列的位置
let insertIndex = i;
// 将当前元素从右到左与有序子列元素比较
// 起始位置为当前元素前一个元素,即i-1,终止位置为0
// 若是当前元素比该有序子列元素小,则该元素后移一位,并修改插入位置的游标
for (let j = i-1; j > -1 && currentValue < originValues[j]; j--) {
originValues[j+1] = originValues[j];
insertIndex = j;
}
// 插入指定位置
originValues[insertIndex] = currentValue;
}
return originValues;
};
复制代码
以上就是直接插入排序的代码实现。整体来讲仍是比较简单易懂,其实就相似于打扑克,不断将扑克牌按顺序插入指定位置。惟一可能有一点容易想不清楚的,就是有序子列的右移部分。想清楚一点,只要有序子列的该元素大于要插入的元素,该元素就要后移一位。ide
1. 时间复杂度
排序算法中,两个元素的比较次数是影响运行时间的首要因素。因此咱们能够经过这个层面来评估。
最优复杂度
当数组有序时,每一次迭代只有一次比较,因此总共有n-1次比较,复杂度为O(n)。
最差复杂度
当数组逆序时,每一次都要比较整个有序子列,比较次数为:
T(n) = 1 + 2 + ... + n-1 = n*n/2
复制代码
因此,最差复杂度是O(n2)。
2. 稳定性
由于比较元素是,相同值不会交换,因此插入算法是稳定的。
本章节介绍了插入排序的实现。插入排序在思路上,和选择排序仍是有些相似的。插入排序的复杂度仍是没有突破O(n2)。
不过,上面的实现只是简单的插入排序,还能够优化。就是在有序子列中找插入位置时,利用二叉查找的方法,这样复杂度能够到O(nlogn)。这里先不作介绍。
[1] 动画演示
[2] tutorials point 教程
[3] Sorting Algorithms
[4] 凯耐基梅隆大学数据结构与算法-排序算法