#P1868. 常见排序算法.插入排序
常见排序算法.插入排序
1. 简介
插入排序,也称为直接插入排序,其排序思想和我们平时打扑克牌时排序类似。
2. 算法步骤
-
在下面的动画中,柱子表示一个个的数字,数字越大,柱子越高。
-
左边的柱子标注为橙色,表示有序的数字,右边浅蓝色的柱子表示还没进行排序的数字。一开始,把第 1 个元素看作已经有序的序列,第 2 到第 n 个个匀速为无序序列。
-
每一轮都是把右边一个无序的数字插入到左边有序的数里。因为左边的数字本身已经有序,找位置插入的原则是:从后往前找,找到第一个小于等于要插入的这个数字的数字,插到这个数字的后面。
-
插入数字的时候,要挪动这个位置及后面的数字,让出一个空位置出来。这个挪动的动作是插入排序很重要的工作开销。如果之前的数字就大致有序,那么挪动的情况就少。如果之前的数字非常杂乱无章,挪动的情况就多。最终排序的时间和原本数字的情况有关,所以,我们说插入排序是一种不稳定的排序算法。
-
一开始,全部数字都是未经排序的。然后,有序的数字逐渐增加(橙色的柱子多起来),无序的数字减少。最后,全部数字都称为有序数字(都称为橙色的柱子)。
3. 效果图:
4. 代码模板
#include<bits/stdc++.h>
using namespace std;
int x[10001];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>x[i]; //数字输入到 x 数组 ,一开始是无序的
int tmp,p; // 有序的数字位于 [l,R] 最开始是 [1,1],x[1] 只有 1 个数,我们认为它就是有序的
for(int i=2;i<=n;i++) // 把 x[2] 到 x[n] 插入到 x[1],x[2],...,x[i-1],
{
for(p=i-1;p>0;p--)
if(x[p]<=x[i]) break; //找到插入的位置
//x[p]<=x[i],所以,x[i]应该 插入到 x[p] 后面
tmp = x[i]; //记录下 x[i]是什么
for(int j=i-1;j>=p;j--) //从 x[p] 到 x[i-1] 全部往后挪一个位置
x[j+1] = x[j];
x[p]=tmp; //x[p] 保存要插入的数字
}
for(int i=1;i<=n;i++) //输出有序的数字
cout<<x[i]<<" ";
return 0;
}
同样的意思,可以改一下,这样写:
#include<bits/stdc++.h>
using namespace std;
int x[10001];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>x[i]; //数字输入到 x 数组 ,一开始是无序的
int tmp,p; // 有序的数字位于 [l,R] 最开始是 [1,1],x[1] 只有 1 个数,我们认为它就是有序的
for(int i=2;i<=n;i++) // 把 x[2] 到 x[n] 插入到 x[1],x[2],...,x[i-1],
{
if(x[i]<x[i-1]) //x[1] 到 x[i-1] 是有序的,x[i-1] 是当中最大的。如果 x[i] 比 x[i-1] 大,那么 x[i] 就是插入到 x[i-1] 后面,就是什么都不用做了
{
for(p=i-1;p>0;p--)
if(x[p]<=x[i]) break; //找到插入的位置
//x[p]<=x[i],所以,x[i]应该 插入到 x[p] 后面
tmp = x[i]; //记录下 x[i]是什么
for(int j=i-1;j>=p;j--) //从 x[p] 到 x[i-1] 全部往后挪一个位置
x[j+1] = x[j];
x[p]=tmp; //x[p] 保存要插入的数字
}
}
for(int i=1;i<=n;i++) //输出有序的数字
cout<<x[i]<<" ";
return 0;
}
5. 稳定性
如果有两个数据元素他们的关键特性是一致的(例如按照大小排序的时候,两个一样大的数字就是具有相同的关键特性),排序前和排序后这两个数据的位置发生了变化,那么我们认为这个排序算法就是不稳定的。
按照上面的代码,插入排序是稳定的。
6. 计算复杂度
假设 x[ ] 数组在排序之前就已经是有序的,x[i] <= x[i+1] ,那么运行上面这个程序就压根没有触发数据插入的那段代码。整个程序就是比较了 n-1 次就完成了比较。
这个问题也是比赛理论题的一个高频考点,就问你数据有序的情况下,插入排序比较了多少次完成排序,答案就是 n-1 。
如果数据一开始是反序的,那么每一次 x[i] 都是插入到 x[1] 的位置,那么计算复杂度就是 O(n^2).