直接插入排序:
基本思想:
把n个待排序的元素看成一个有序表和一个无序表,开始时有序表中只有一个元素,无序表中有n-1个元素;排序过程即每次从无序表中取出第一个元素,将它插入到有序表中,使之成为新的有序表,重复n-1次完成整个排序过程。
实例:
0.初始状态 3,1,5,7,2,4,9,6(共8个数)
有序表:3;无序表:1,5,7,2,4,9,6
1.第一次循环,从无序表中取出第一个数 1,把它插入到有序表中,使新的数列依旧有序
有序表:1,3;无序表:5,7,2,4,9,6
2.第二次循环,从无序表中取出第一个数 5,把它插入到有序表中,使新的数列依旧有序
有序表:1,3,5;无序表:7,2,4,9,6
3.第三次循环,从无序表中取出第一个数 7,把它插入到有序表中,使新的数列依旧有序
有序表:1,3,5,7;无序表:2,4,9,6
4.第四次循环,从无序表中取出第一个数 2,把它插入到有序表中,使新的数列依旧有序
有序表:1,2,3,5,7;无序表:4,9,6
5.第五次循环,从无序表中取出第一个数 4,把它插入到有序表中,使新的数列依旧有序
有序表:1,2,3,4,5,7;无序表:9,6
6.第六次循环,从无序表中取出第一个数 9,把它插入到有序表中,使新的数列依旧有序
有序表:1,2,3,4,5,7,9;无序表:6
7.第七次循环,从无序表中取出第一个数 6,把它插入到有序表中,使新的数列依旧有序
有序表:1,2,3,4,5,6,7,9;无序表:(空)
template<typename T> //泛型 void insertionSort(T arr[], int n){ //数组arr 个数n for(int i=1;i<n;i++){ //寻找元素arr[i]合适的插入位置 //合适的插入位置在前面所以j从i开始,j--,将arr[i]与它的前一个位置的元素比较 for(int j=i;j>0;j--){ if(arr[j] < arr[j-1]) swap(arr[j],arr[j-1]); else break; } } }
也可以简写为:
template<typename T> //泛型 void insertionSort(T arr[], int n){ //数组arr 个数n for(int i=1;i<n;i++){ //寻找元素arr[i]合适的插入位置 //而合适的插入位置在i的前面,所以j从i开始,j--,将arr[i]与它的前一个位置的元素比较 //同时满足 j>0 && arr[j] < arr[j-1] 这两个条件就可以交换了 for(int j=i;j>0 && arr[j] < arr[j-1];j--){ swap(arr[j],arr[j-1]); } } }
插入排序和选择排序最大的区别是:选择排序没有提前终止的条件,必须要遍历一遍数组找到当轮的最小值
但是 swap() 交换操作比比较操作更耗时(因为交换操作需要进行三次赋值),所以插入排序反而比选择排序更耗时。
优化方法:
将交换操作改为比较操作,此时插入排序比选择排序的运行时间更短(因为可以提前终止内层循环)。
template<typename T> //泛型 void insertionSort(T arr[], int n){ //数组arr 个数n for(int i=1;i<n;i++){ //寻找元素arr[i]合适的插入位置 T e = arr[i]; int j; //j保存元素e应该插入的位置 //若j前面的元素比e还要大,则当前找到的j不是e要最终放的位置(因为从小到大排列) for(j=i; j>0 && arr[j-1]>e ;j--){ arr[j] = arr[j-1]; } arr[j] = e; } }
优化后的插入排序算法对于近乎有序的数组的性能较高。