C++算法之插入排序
文章目录
一、算法描述
整理插入排序算法描述如下:
- 枚举序列中第
2~n个元素。 - 当枚举元素i时,前
i-1个元素已经有序。将第i个元素插入到前i-1个元素的有序序列中,形成长度为i的有序序列。 - 枚举过程结束后,整个序列有序。
在上述算法描述中,我们有个关键的步骤——插入操作:将第i个元素插入到前i-1个元素的有序序列中,形成长度为i的有序序列。
怎样实现这个过程呢?
一种实现思路和前面介绍的“火车站插队”过程十分类似。比如对于如下序列:

这个序列的前4个元素已经有序,现在我们要把2插入到前4个元素中去。
1、首先让2出队。

2、然后将其与6比较,发现2<6,说明2应该在6前面。所以我们将6向后移动。
3、再将其与5比较,发现2<5,说明2应该排在5前面。所以我们将5向后移动。


4、经过同样的分析,4也应该向后移。

5、最后我们将2与1比较,发现1<2,说明2应该放在1的后面。正好经过前面的移动,1后面有一个空位,所以我们把2插入在这个空位中。

以上就是我们将一个新的元素2插入前面有序序列a的过程。
因为前面的序列有序,所以在整个序列中一定有一条分界线j,使得分界线前面的元素(i<j),都满足a[i]<=2;
对于分界线及分界线以后的元素(i>=j),都满足a[i]>2;
所以,上面的移动一定可以将分界线及以后的元素向后移动一位,空出分界线的位置j,然后将2插入到j号元素中。
所以,我们总结一下插入操作的算法描述:
-
假设序列
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)










