插入排序算法里的直接插入,算法核心是将待插入的数插入到已排序好的一些数中,并放到正确的位置上(通过前后数交换),再处理下一个待插入数,直到所有数都在正确的位置上。
举一个例子,比如我们有个数组 a[4]={4,7,2,3},现在要用插入排序算法将这个数组从小到大排序,首先我们用 i 来表示待插入数的下标,比如第一个待插入数为 a[1]=7,如果我们设定 i 是从0开始的,那么待插入数应为表示为 a[ i+1 ],i 应该从0到2,这是第一层循环。
接下里我们将这个待插入数放入前面已经排序好的数中(当然此时只有4一个数,肯定是排序好的),如何才能将这个待插入数放到正确的位置上呢,最简单的方法就是不断和前一个数比较,如果大于前面一个数表示位置符合从小到大,不用变了;如果小于前一个数,表示位置不对,那么就要和前一个数交换位置,然后继续重复和再前一个数比较的过程。如果运气不好,待插入数前有几个数,我们就需要做几次交换,所以这就需要另一层循环了,我们用 j 来表示,第一次交换时候 j=0,第二次交换的时候 j=1,以此类推。那么我们用这两层循环即可完成这个排序。
我们可以看看这些数的位置变化过程:
a [ ] 0 1 2 3
4 7 2 3
i=0 , j=0 4 7 2 3
i=1 , j=0 4 2 7 3
j=1 2 4 7 3
i=2 , j=0 2 4 3 7
j=1 2 3 4 7
j=2 2 3 4 7
下面我们用伪代码来表示一下详细的流程:
外层循环: i=0,i=1,i=2 → for(i=0 ; i<3 ; i++)
i=0 , j=0 if a[0]<a[1] break → if a[ i-j ]<a[ i-j+1 ] break → 很容易发现,所有下标我们都可以用i j 来统一表示
else a[0] <–>a[1] → else a[ i-j ] <–>a[ i-j+1 ]
这里内层循环执行了1(i+1)次
i=1 , j=0 if a[1]<a[2] break → if a[ i-j ]<a[ i-j+1 ] break
else a[1] <–>a[2] → else a[ i-j ] <–>a[ i-j+1 ]
j=1 if a[0]<a[1] break → if a[ i-j ]<a[ i-j+1 ] break
else a[0] <–>a[1] → else a[ i-j ] <–>a[ i-j+1 ]
这里内层循环执行了2(i+1)次
i=2 , j=0 if a[2]<a[3] break → if a[ i-j ]<a[ i-j+1 ] break
else a[2] <–>a[3] → else a[ i-j ] <–>a[ i-j+1 ]
j=1 if a[1]<a[2] break → if a[ i-j ]<a[ i-j+1 ] break
else a[1] <–>a[2] → else a[ i-j ] <–>a[ i-j+1 ]
j=2 if a[0]<a[1] break → if a[ i-j ]<a[ i-j+1 ] break
else a[0] <–>a[1] → else a[ i-j ] <–>a[ i-j+1 ]
这里内层循环执行了3(i+1)次
那么,我们可以得出内层循环应该这样写 for( j=0 ; j< i+1 ;j++)
好了,到这里我们已经很容易得到这个算法的代码了。
int a[4]={4,7,2,3};
int i,j,t;
for(i=0;i<3;i++){
for(j=0;j<i+1;j++){
if(a[i-j]<a[i-j+1]){break;}
t=a[i-j];
a[i-j]=a[i-j+1];
a[i-j+1]=t;
}
}