总结
-
插入排序的基本思想就是不断扩展有序序列的长度。
具体方式是对于一个有序序列,如果想在其中新加入一个元素,就应通过插入操作找出正确的插入位置,并且将插入位置空出来,然后插入新元素。
-
插入操作的基本思想就是从后向前不断“试探”分界线的位置。
一个合法的分界线,分界线前的元素需满足小于等于新元素大小,分界线后元素需满足大于新元素大小。所以寻找分界线的过程,就是不断把当前在分界线前,但本应该在分界线后的元素向后移动。
-
插入操作的算法描述:
- 假设序列
1~(i-1)已经有序, 从i到1枚举分界线的下标j; - 如果分界线前面的元素
a[j-1]大于x,说明a[j-1]应该在分界线后面。所以将a[j-1]移动到a[j],分界线前移变成j-1。 - 如果分界线前面没有元素(
j=1),就将x放在数组第1位。否则如果碰到一个j-1号元素小于等于x,说明分界线位置正确,就将x插到j位。
- 假设序列
-
完整插入排序的代码实现:
#include <bits/stdc++.h>
#define N 1550
using namespace std;
int a[N], n;
int main() {
// 输入
cin >> n;
for (int i = 1; i <= n; ++i) cin >> a[i];
// 插入排序
for (int i = 2; i <= n; ++i) { // 按照第2个到第n个的顺序依次插入
int j, x = a[i]; // 先将i号元素用临时变量保存防止被修改。
// 插入过程,目的是空出分界线位置j,使得所有<j的部分<=x,所有>j的部分>x。
// 循环维持条件,j>1,并且j前面的元素>x。
for (j = i; j > 1 && a[j - 1] > x; --j) {
// 满足循环条件,相当于分界线应向前移,
// 分界线向前移,就等于将分界线前面>x的元素向后移
a[j] = a[j - 1];
}
// 找到分界线位置,插入待插入元素x
a[j] = x;
}
// 输出
for (int i = 1; i <= n; ++i) cout << a[i] << ' ';
cout << endl;
return 0;
}
- 时间复杂度分析:
插入排序的总时间复杂度是O(n^2)O(n2)。