直接插入排序
- 基本思想:将序列第一个记录看作有序的,将后面的记录依次插入到已排好序的序列中。
- 具体操作:假设第一个已经有序,对后面每个元素循环插入:如果从小到大排序,要插入的那个值如果大于末尾那个,就没必要插了。否则从末尾朝前找,直到那个值大于等于a[j]。然后插入位置当然是a[j+1]。
- 代码实现:哨兵放在\(a[0]\)
- 不放哨兵的话,就要判断边界
a[i]<a[j] && j>=0
void insertsort(int a[], int n){
for(int i=2;i<=n;i++){
if(a[i]<a[i-1]){
a[0] = a[i];
for(int j=i-1; a[0]<a[j]; j--){
a[j+1] = a[j];
}
a[j+1] = a[0];
}
}
}
- 空间复杂度:\(O(1)\) 常数个辅助空间
- 时间复杂度:插入元素\(n-1\)次,每次要比较和移动,其次数取决于待排序序列的原始状态
- 最好情况:序列有序,每次插入,只需比较一次,不用移动,\(O(n)\)
- 最坏情况:序列逆序,插入元素\(n-1\)次,总的比较次数最大\(\sum\limits_{i=2}^n{i}\) ,总的移动次数最大\(\sum\limits_{i=2}^n{(i+1)}\)
- 平均情况:元素随机,期望值可以取最好最坏的平均,总的比较和移动次数约为\(n^2/4\)
- 由此:直接插入排序算法时间复杂度为\(O(n^2)\) 实际看代码也能看出
- 稳定性:稳定排序
- 因为是从后往前比较再移动,所以遇到相同元素就肯定停下来了,所以相对位置不会改变
- 适用性:顺序和链式(链式时也可以从后往前查找),大部分排序都只适合顺序
折半插入排序
- 可以优化的地方:在有序序列中查找一个比那个值更小的时,可以用二分