开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,点击查看活动详情
插入排序原理:
算法的着力点在于有序序列,开始定位一个对象,作为最小的已排序的序列。和我们打扑克的思路是一样的,未抓取的是未排序序列,手里的牌是已排序序列,未排序抓取一张和手里的牌对比,并插入正确位置,直到抓完牌,排序也就完成了。
可以看出直接插入模式虽不需要额外空间,但比较的过程中会有较多的交换操作,已排好序的序列可能会不断的往后挪位。
这中间不会出现对象相对位置的变化,所以他是稳定的算法。它的最好时间复杂度是O(n),一般和最差时间复杂度O(n2)。
一般流程:
- 选择第一个对象为已排好的序列;
- 第二个对象和第一个对象比较,大于或者等于不挪位,小于则两者交换位置,第一二位置排序完成;
- 如上思路,如果排序已完成n-1个对象,第n个位置依次往前位置比较。小于的情况下交换位置,直到找到大于等于的情况为止;
- 直到完成全部对象的选取,则完成无序序列的排序。
代码实例:
#include<stdio.h>
#include <stdlib.h>
#include<unistd.h>
#include <string.h>
#include <errno.h>
#define SWAP(a1, a2, type) do {type temp = a1; a1 = a2; a2 = temp;} while(0)
int Cnt = 0;
int NumArr[200] = {0};
void PrintNums()
{
for(int i = 0;i < Cnt;i++){
fprintf(stdout," %d-",NumArr[i]);
}
}
int main(int argc, char** argv)
{
if(argc == 1) {
fprintf(stderr,"%s:need a some arg\n",argv[0]);
exit(1);
}
int CntTemp = Cnt = argc -1;
for(int i = 0;i < Cnt;i++){
NumArr[i] = atoi(argv[i+1]);
}
fprintf(stdout,"【Insertion Sort】inputNum:");
PrintNums();
fprintf(stdout,"\n");
for(int a = 1;a < Cnt;a++){
for(int b = a;0 < b;b--){
if(NumArr[b] < NumArr[b-1]) SWAP(NumArr[b],NumArr[b-1],int);
}
}
fprintf(stdout,"result:");
PrintNums();
fprintf(stdout,"\n");
return 0;
}
测试结果,如下
优化方式:
在比较位置插入数值的过程中,因为是与有序序列比较,所以可以用二分法减少比较次数,比较次数可以较少一半,优化时间复杂度。