例如,已知待排序的一组记录的初始排列如下所示:
R(49),R(38),R(65),R(97),R(76),R(13),R(27),R(49),…
假设在排序过程中,前4个记录已按关键字递增的次序重新排列,构造一个含4个记录的排序序列
{ R(38), R(49), R(65),R(97)}
现需要将第五个(即关键字为76)记录插入上述序列,以得到一个新的含5个记录的有序序列,则首先要在序列中进行查找R(76)所以插入的位置,然后进行插入。假设从R(97)起从左进行顺序查找,由于65<76<97,则R(76)应插入在R(65)和R(97)之间,从而得到下列新的有序序列
{ R(38), R(49), R(65), R(76), R(97)}
将此过程称为一趟直接插入排序。一般情况下,第i趟直接插入排序的操作为:在含有i-1个记录的有序子序列r[1..i-1]中插入一个记录r[i]后,变成含有i个记录的有序子序列r[1..i];并且和顺序查找类似,为了在查找插入位置的过程中避免数组下标出界,在r[0]处设置监视哨。在自i-1起往前搜索的过程中,可以同时后移记录。整个排序过程为进行n-1趟插入,即:先将序列中的第1个记录看成一个有序的子序列,然后从第2个记录起逐个进行插入,直至整个序列变成关键字非递减有序序列为止。
算法如下:
void InsertSort () { // 对顺序表L作直接插入排序 for ( i=2; i<= length; ++i ) //进行n-1趟 if ( r[i] < r[i-1] ) { // 将r[i] 插入有序子表 r[0] = r[i]; r[i]=r[i-1]; for ( j=i-2; r[0] < r[j]; --j ) r[j+1] =r[j]; // 记录后移 r[j+1] = r[0]; // 插入到正确位置 } // if } // InsertSort
排序中的两个基本操作是:(关键字间的)比较和(记录的)移动。因此排序的时间性能取决于排序过程中这两个操作的次数。从直接插入排序的算法可见,这两个操作的次数取决于待排记录序列的状态,当待排记录处于"正序"(即记录按关键字从小到大的顺序排列)的情况时,所需进行的关键字比较和记录移动的次数最少,反之,当待排记录处于"逆序"(即记录按关键字从大到小的顺序排列)的情况时,所需进行的关键字比较和记录移动的次数最多,如下表所列。
排序插入是稳定的。
示例:
#include<stdio.h> int main() { int i,j,a[11]; for(i=1;i<11;i++) scanf("%d",&a[i]); for(i=2;i<11;i++) if(a[i]<a[i-1]) //插入a[i] { a[0]=a[i]; //a[0]起监视哨的作用 ,无需担心j越界 a[i]=a[i-1]; for(j=i-2;a[0]<a[j];j--) a[j+1]=a[j]; a[j+1]=a[0]; } for(i=1;i<11;i++) printf("%d ",a[i]); return 0; }或者做小改动为
#include<stdio.h> int main() { int i,j,a[11]; for(i=1;i<11;i++) scanf("%d",&a[i]); for(i=2;i<11;i++) { a[0]=a[i]; for(j=i-1;a[0]<a[j];j--) a[j+1]=a[j]; a[j+1]=a[0]; } for(i=1;i<11;i++) printf("%d ",a[i]); return 0; }动态图:
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/zd2014zd/article/details/47659413