插入排序的基本思想就是将待排序的数据按照其关键码值的的大小逐个插入到一个已经排好序的有序序列之中,知道所有的数据插入完为止,就得到一个新的有序数列.
现在从例子中具体来看.
假如现在有一组数据为
5 2 4 6 1 3
因为只有一个数字的话,那它本身可以看作是有序的
因此我们从第二个数开始,将2与5比较,2 < 5,所以要将2放在5的前面,这组数据就变成了
2 5 4 6 1 3
现在这组数据2 5可以看作有序数列,然后将4插入到该有序数列的正确位置. 4 < 5, 4与5交换,4 > 2保持不动,数据变为
2 4 5 6 1 3
现在这组数据2 4 5是已排好序的数据.再看6, 6 > 5保持不动,即此时2 4 5 6有序.
再看1, 1 < 6,交换, 1 < 5继续交换,直至找到2, 1插入到了有序数据的最前端停止.数据变为
1 2 4 5 6 3
最后看3, 3 < 6交换,3 < 5交换, 3 < 4交换, 3 > 2结束
至此数据排列完成
1 2 3 4 5 6
不难发现整体数据其实划分为了两部分,一部分有序,一部分无序,而我们要做的就是将无序数据逐个插入到有序数组中正确的位置上.
考虑到每次插入的时候其实是一个循环比较的过程,我们可以在每次循环的开始,将本次循环需要的插入的数据保存在tmp中.这样插入过程其实渐变成了一个平移的过程
假如1 2 4 5 6 3这组数据,我们要插入3
我们将3保存下来 tmp = 3
开始循环比较找到应该插入的位置,在没有找到以前数据向后平移覆盖,即 6 覆盖 3, 5 覆盖 6, 4 覆盖 5,至此找到3 应该插入的位置,将一开始保存的3覆盖4.这样就完成了一个插入排序.
完整代码可参考下面:
#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE 10000
void InsertSort(int* src, int n){
int i, j;
int tmp;
for (i = 1; i < n; ++i){
tmp = src[i]; //将本次需要插入的数字保存
for (j = i; j > 0 && src[j - 1] > tmp; --j){
src[j] = src[j - 1]; //确定该数字插入的位置,并进行平移覆盖
}
src[j] = tmp; //将一开始保存的数字覆盖回去
}
}
void printArray(int* src, int n){
int i;
for (i = 0; i < n; ++i){
printf("%d ", src[i]);
}
putchar('\n');
}
int main(){
#if 0
//int src[10] = { 3, 1, 6, 7, 9, 2, 4, 8, 10, 5 };
int src[11] = { 1, 3, 6, 7, 9, 2, 4, 8, 10, 5, 11 }; //对插排的测试(较小的数据量)
InsertSort(src, 11);
printArray(src, 11);
#else
srand((unsigned int)time(NULL));
int src[BUFSIZE];
int i;
for (i = 0; i < BUFSIZE; ++i){
src[i] = rand() % 5000 + 1;
}
InsertSort(src, BUFSIZE); //对插排的测试(较大数据量)
printArray(src, BUFSIZE);
#endif
system("pause");
return 0;
}
插入排序的特性:
1.元素集合越接近有序,插入排序的算法效率越高
2.数组规模较小时,插排最优
3.时间复杂度O(N^2)
4.稳定性: 稳定