1、插入排序的简单介绍
直接插入排序是一种简单的排序方法,和选择、冒泡一样,是一种稳定的排序方法,时间复杂度和空间复杂度和它们一样,分别是O(n^2)和O(1),插入排序的基本思想是将一个待定的元素与一个已经有序的部分元素进行比较,确定一个插入的位置后,将这个待定的元素插入到这个位置,以这个方式一直进行插入,直到整个序列有序。要这个插入的过程,一般我们采用的顺序存储结构,而不是链表,所以确定一个插入的位置之后,就要将所位置之后的部分有序的元素将后推移,以将这个位置腾出来,将待定的元素插入。
2、一般的插入排序实现方式
2.1、一个外层循环确定待定的元素下标
2.2、第二层循环确定插入的位置
2.3、第三层循环将元素后移,最后将待定的元素插入腾出来的位置中
可以看出,这样的话,一般情况下的时间复杂度是 O(n^3),所以可以某些方面做些优化:假设现在要将第i个元素插入,说明从0到i-1这部分元素是已经有序的,只有当i和i-1逆序时,才会产生插入逻辑,不然i元素位置不动,当前序列也是有序的,也就是说,可以上面第二层和第三层循环优化成一个循环,将寻找位置与后推两个动作放在同一个循环体中完成。void tranInsertSort(int *arr) { int i,j,k,key; for(i=1; i<M; i++) //控制当前被插入的元素下标 { key=arr[i]; for(j=i-1; j>-1&&arr[j]>key; j--); //寻找插入的位置 if(j!=i-1) { for(k=i; k>j; k--)//将(j,i]范围内元素后移,将j位置空出来 arr[k]=arr[k-1]; arr[k+1]=key; } } }
3、简化后插入排序
这些简化之后,整个程序的篇幅缩短,实际运行的时间复杂度也得到了优化,将复杂度降低到 O(n^2)。void insertSort(int *arr) { int i,j,key; for(i=1; i<M; i++) { if(arr[i-1]>arr[i])//当前元素i比元素i-1要小,说明前面i应该排在i-1之前 { key=arr[i]; for(j=i; j>0&&arr[j-1]>key; j--) arr[j]=arr[j-1];//将元素向后推移 arr[j]=key; } } }