直接插入排序
排序过程
基本原理
对长度为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、二分查找法
在一个有序的序列中查找一个给定的元素,最快的方法无疑是二分查找法,但是存在一个缺点,即算法的稳定性会被破坏。既然一定要破坏算法的稳定性,那么可以直接使用更加优秀的希尔排序。