直接插入排序


 

排序过程


 

基本原理

长度为n的序列A进行排序,假设序列中存在两个区间——有序区间[ 0 , i ]、无序区间[ i+1 , n-1 ]

(1)遍历有序区间[ 0 , i ],找到一个合适的位置插入无序区间[ i+1 , n-1 ]中的元素A[i+1]

(2)有序区间扩充为[ 0 , i+1 ],无序区间缩小为[ i+2 , n-1 ];

(3)重复以上过程,直到有序区间扩充为[ 0 , n-1 ],即排序完成。

 


 

思考

1、遍历次数?比较次数?移动次数?

  最好情况,即序列恰好有序:

       遍历次数 = n-1

       比较次数 = n-1

       移动次数 = 0

  最坏情况,即序列完全逆序:

       遍历次数 = n-1

       比较次数 = 移动次数 =  n(n-1)/2

遍历序号:  a1     a2    a3    ...   an-2   an-1

移动次数:  n-1   n-2   n-3  ...    2    1

总移动数: (等差数列求和)Sn = (n-1)(n-1+1)/2 = n(n-1)/2 

2、时间复杂度?空间复杂度?算法稳定性?

    时间复杂度:O( n2 )

    空间复杂度:O( 1 )

    算法稳定性: 稳定

3、什么情况下适合使用直接插入排序?直接插入排序算法在什么情况下更加高效?

    序列规模较小、序列有序程度高


 

优化

  优化直接插入排序算法的突破口在于:如何快速找到合适的插入位置?

  1、设置哨兵位

    记录前一次遍历插入的元素A[x]以及插入的位置x。若本次遍历待插入的元素A[i+1]小于A[x],直接将区间[ x , i]内所有元素向后移动一个位置,然后在区间[ 0 , x-1]寻找合适的插入位置;若本次遍历待插入的元素A[i+1]等于A[x],直接将区间[ x+1 , i]内所有元素向后移动一个位置,然后将A[i+1]插入下标为x+1的位置;若本比遍历待插入的元素A[i+1]大于A[x],则按照老方法在区间[ 0 , i ]寻找合适的插入位置。

  2、二分查找法

    在一个有序的序列中查找一个给定的元素,最快的方法无疑是二分查找法,但是存在一个缺点,即算法的稳定性会被破坏。既然一定要破坏算法的稳定性,那么可以直接使用更加优秀的希尔排序。