插入排序
核心思想:一个无序数组,将第一个数看做是有序的,将后面的数依次插入到前面有序数列,通过比较,插入到正确位置,从而形成新的有序数列。
从他的核心思想中,我们可以提取出两个点。一是:将后面看做无序的数列,依次插入前面,这是第一层外循环,控制插入多少次,也就是后面有多少个数;二是:插入的时候,与前面有序数列进行比较,插入到正确位置,这是第二次内循环,控制要比较多少次才能插入到正确位置,也就是有序数列的个数。
明白这两个点后,就可以着手开始写了。
如果你不知道,怎么写这两次循环,像我上篇文字讲的一样,先从第一个数插入比较开始。
- 先写个数组,打印出来,增加点信心。
int a[]={9,3,5,7,1,4,2,8,6};
int length=sizeof(a)/sizeof(a[0]);
for(auto i:arr) cout<<i<<" ";
- 外循环
for(int i=1;i<length;i++){ //从1开始,第2个数
}
- 内循环,其实就是看前面排序好的数列有几个嘛,然后再让要插入的数字去一个一个比较。
倒着,往前插,把循环开始的位置,设为排序好的最后一个,倒着循环,依次比较
for(int j=i;j>0;j--){//从i开始的位置
//依次向前比较
if(a[j]<a[j-1]){
swap(a[j],a[j-1]);
}
}
- 合在一起
for(int i=1;i<length;i++){
for(int j=i;j>0;j--){
//依次向前比较
if(a[j]<a[j-1]){
swap(a[j],a[j-1]);
}
}
}
这样一个基本的插入排序就写好啦。还是要自己多思考,多练习,多上手!
优化
在插入排序中需要对序列元素进行频繁的swap操作,这是非常耗时间的。所以我们只要减少甚至消除swap操作,插入算法的时间消耗会减少。
方法:用临时变量记录标记项,去掉swap方法。
把要插入的数,临时标记,找到要插入的正确位置后,把后面的数依次向后挪,而不是交换。
void insertSort(int a[], int length) {
for (int i = 1; i < length; i++) {//抽出第i个数
int temp = a[i];//标记
int j;
for (j = i; j > 0; --j) {
if (temp < a[j - 1]) {
a[j] = a[j - 1]; //向后挪
}
else {
break;
}
}
a[j] = temp;
}
}
插入排序的时间复杂度是O(N^2),空间复杂度是O(1)。
End.