直接插入排序的思想是:将一个记录插入到已排序好的有序表中,从而得到一个新,记录数增1的有序表。即:先将序列的第1个记录看成是一个有序的子序列,然后从第2个记录逐个进行插入并排序,直至整个序列有序为止。
算法中引进的附加记录R[0]称监视哨或哨兵(Sentinel)。
哨兵有两个作用:
① 进人查找(插入位置)循环之前,它保存了R[i]的副本,使不致于因记录后移而丢失R[i]的内容;
② 它的主要作用是:在查找循环中”监视”下标变量j是否越界。一旦越界(即j=0),因为R[0].可以和自己比较,循环判定条件不成立使得查找循环结束,从而避免了在该循环内的每一次均要检测j是否越界(即省略了循环判定条件”j>=1”)。
void InsertSort(int arr[],int n)
{
int i,j;
for(int i = 2;i < n;i++)//从第二元素开始执行,但r[0]为哨兵位,故第二元素下标为2
{
if(arr[i]<arr[i-1])
{
arr[0] = arr[i];//保留在哨兵位
for(j = i - 1;arr[j]>arr[0];--j)
arr[j+1] = arr[j];
arr[j+1] = arr[0];//跳出for循环前执行了减一操作,故下标为j+1
}
}
}
直接插入排序的时间复杂度是O(N2)。同时也是稳定的算法.
算法稳定性 – 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。