插入排序insertsort的基本思想为每一位上的数字都与它前面的每个数字进行比较(顾名思义为把数组上的每一位数字都与其前面的数字进行比较并插入合适的位置),若前面的一个数字比它大,则交换它们两个的位置,然后再次比较该位置前一位数是否仍然比其大,若成立,则继续交换,否则轮到下一个检测位重复上面的操作,这样,所有位上面的数字都能够与其前面的数字进行比较并占到符合自己的位置,相比于选择排序,插入排序的一个优点是提前终止,不用遍历整个数组,因此,插入排序应该要比选择排序的效率更加的高效,以下是插入排序的简单代码实现:
#ifndef INSERTSORT_H_INCLUDED
#define INSERTSORT_H_INCLUDED
#include<iostream>
using namespace std;
template<typename T>
void insertsort(T arr[],int n)
{
for(int i=1;i<n;i++)
{
for(int j=i;j>0&&arr[j]<arr[j-1];j--)
{
swap(arr[j],arr[j-1]);
}
}
}
#endif // INSERTSORT_H_INCLUDED
接下来我们在与选择排序法比较一下排序100000个数据所花费的时间:
我们惊奇的发现:为什么插入排序所花费的时间竟然要比选择排序的时间还要长?插入排序不是可以提前终止的吗?按理来说遍历的次数应该要比选择排序多得多,为什么会出现这样的问题呢?
让我们来仔细的分析一下:插入排序虽然比选择排序能够提前的终止,但是,插入排序每次换位置时都需要进行swap操作,而一个swap操作就包含了三次赋值操作,这将会大大的增加程序运行时间,这就不难解释为什么插入排序还要比选择排序花费的时间还要多了。
那插入排序有什么好的优化吗?当然有,首先我们分析出造成插入排序算法花费时间较多的操作就是循环中的每次swap操作,因此我们需要尽量减少进行swap交换操作的执行,所以我们可以这样修改原来的插入排序算法,首先复制一份待插入的值(我们暂且标记为插入位,后文都为了方便都记做插入位),然后把该值一直与插入位前面的数字比较(该步骤与原来的插入排序算法一样),但是,我们每次比较,如果前面的数字比插入位大,我们不进行交换,而是让插入位被赋值为前面的大数,以此类推,若前面一直有数字比插入位大,则都让这些数字“往后挪一位”,直到发现没有比自己更高的数字了,就把插入位的数值直接赋值给现在这个位置,具体的代码实现如下:
#ifndef PINSERTSORT_H_INCLUDED
#define PINSERTSORT_H_INCLUDED
#include<iostream>
using namespace std;
template<typename T>
void pinsertsort(T arr[],int n)
{
for(int i=1;i<n;i++)
{
T e=arr[i];
int j;
for(j=i;j>0&&arr[j-1]>e;j--)
{
arr[j]=arr[j-1];
}
arr[j]=e;
}
}
#endif // PINSERTSORT_H_INCLUDED
改进后的插入排序暂且命名为pinsertsort,接下来让我们比较一下insertsort(),pinsertsort()以及selectsort()三个排序函数的效率,我们还是以排序100000个数据为标准比较其所花费的时间来判断其效率。
以下为三者所花费的时间:
我们不难发现,改进后的插入排序pinsertsort花费的时间最短,效率大大的提升了,大大的超过了选择排序,体现出了插入排序的高效率。
插入排序虽然和选择排序虽然一样都为O(n^2)的复杂度,但是在有的时候,插入排序的效率要大大的超出选择排序的效率,例如当数组如果只有部分无序,也就是说数组处于高度有序的状态的时候,插入排序相比于选择排序可以提前结束的优势就得到了大大的体现了,因此,我们可以改写生成函数,使其生成的函数高度有序,以下是生成函数的改写代码:
int*generatenearorder(int n,int swaptimes)
{
int*arr=new int[n];
srand(time(NULL));
for(int i=0;i<n;i++)
{
arr[i]=i;
}
for(int i=0;i<swaptimes;i++)
{
int x=rand()%n;
int y=rand()%n;
swap(arr[x],arr[y]);
}
return arr;
}
让我们在测试一次有100000个数据,其中有100对数据无序的一个高度有序的数组,测试的函数有三个,分别是选择排序(selecesort),插入排序(insertsort)以及优化过后的插入排序(pinsertsort),以下为测试数据:
由此我们可以看出,在高度有序的数组排序中,插入排序以及优化后的插入排序相比于选择排序效率大大的提高了,虽然二者都是O(n^2)的复杂度。