插入排序的工作机理跟打牌时整理手中的牌差不多,开始摸牌时,我们左手是空的,牌面朝下放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将它与手中已有的每一张牌从右到左地进行比较。

算法的伪代码如下所示:

INSERTION-SORT(A)1    for j <— 2 to length[A]2       do k <— A[j]3             Insert A[j] into the sorted sequence A[1..j-1].4            i <— j - 15            while i > 0 and A[i] > key6                do A[i+1] <— A[i]7                    i <— i - 18            A[i+1] <— key

 

回到顶部

伪代码中的约定:

1.书写上的“缩进”表示程序中的分程序(程序块)结构

2.while,for,repeat等循环结构和if,then,else条件结构与Pascal中相同

3.符号“”表示后面部分是注释

4.多重赋值i<—j<—e 是将表达式e的值赋给变量i和j;等价于赋值j<—e,在进行赋值i <—j

5.变量(如i,j和key等)是局部于给定过程的。在没有显示说明的情况下,我们不使用全局变量

6.数组元素是通过“数组名[下标]”这样的形式来访问的

7.复合数据一般组织成对象,它们是由属性或域所组成的

8.参数采用按值传递方式:被调用的过程会收到参数的一份副本

9.布尔运算符“and”和“or”都具有短路能力

 

回到顶部

算法分析:

首先给出 INSERTION-SORT 过程中,每一条指令的执行时间及执行次数。对j=2,3,...,n,n=length[A],设tj为地5行中while循环所做的测试次数。当for或while以通常方法退出(即,因为循环头部的测试条件不满足而退出)时,测试要比循环体多执行一次。另外,还假定注解部分是不可执行的,因而不占运算时间。

对上面伪代码分析如下:

sequence    cost    times

  1        c1      n

  2       c2       n-1

  3       0      n-1

  4       c4      n-1

  5       c5       

  6       c6       

  7       c7       

  8       c8       n-1

该算法总的运行时间是每一条语句执行时间之和。如果执行一条语句需要ci步,又共执行了n次这条语句,那么它在总运行时间中占cin。为计算总运行时间T[n],对每一对cost与times之积求和,得:

  

即使是对给定规模的输入,一个算法的运行时间也有可能要依赖于给定的是该规模下的哪种输入。

如果输入数组已经是排好序的话,就会出现最佳情况。对j=2,3,...,n中的每一个值,我们发现,在第五行中,当i取其初始值 j-1 时,都有A[i]≤key。于是,对j=2,3,...,n,有tj=1,最佳运行时间为:

  

       

这一运行时间可以表示为 an+b,常量a和常量b依赖于语句的代价ci;因此,它是n的一个线性函数。

如果输入数组是按照逆序排序的,那么就会出现最坏情况,运行时间为:

  

       

       

 

注:  

这一最坏情况运行时间可以表示为an2+bn+c,常量a,b,c仍依赖于语句的代价ci;因此,这是一个关于n的二次函数。

回到顶部

算法实现

以下是JavaScript代码对其算法的实现:

 1 'use strict'; 2 function insertionSort(Arr) { 3     for(let j = 1,len = Arr.length; j < len; j++) { 4         let key = Arr[j]; 5         let i = j - 1; 6         while (i > 0 && Arr[i] > key) { 7             Arr[i + 1] = Arr[i]; 8             i--; 9         }10         Arr[i + 1] = key;11     }12 }