小白学算法2.3——插入排序
标签: 小白学算法
1.插入排序算法
插入排序属于初级排序,时间复杂度为
O(n2)
。n
个数进行插入排序,需要n-1
次排序,每次排序交换的次数取决于待排序的数列本身。插入排序假设最左边的数是最小的数,然后向右遍历,如果第二个数比第一个数小,则交换两个数的位置,反之不交换,结果是前两个数组成有序数列。继续向右遍历,如果第三个数比第二个数小,则交换第二个数和第三个数的位置,继续比较新的第二个数和第一个数,如果新的第二个数比第一个数小,则交换其位置,反之不交换,结果是前三个数组成有序数列。
以此类推,在第i-1
次排序中,前i
个数组成的数列有序,只需要把第i+1
个数插入到前面有序数列中的合适位置,使得前i+1
个数组成的数列依旧有序即可。遍历完数列,排序也就完成了。
现在使用插入排序对数列{5, 7, 1, 4, 2}
进行排序:
i
表示排序的次数,j
表示某次排序比较的两个数中较大的下标- 黄色表示本次比较发生交换的两个数
2.插入排序实现
void insertionSort(int* A, int n)
{
for (int i=1; i<n; i++)
for (int j=i; j>0 && A[j]<A[j-1]; j--)
swap(A, j, j-1);
}
3.插入排序改进
有一个方法可以大幅度的减少插入排序所消耗的时间,那就是减少元素访问的次数,只需要在内循环中将较大的元素向右移动而不是交换两个元素,就能使访问数组的次数减半。
//插入排序改进版
void insertionSort(int* A, int n)
{
for (int i=1; i<n; i++)
{
int insertData = A[i];
for (int j=i; j>0 && insertData<A[j-1]; j--)
A[j] = A[j-1];
A[j] = insertData;//for循环执行一次j--后才跳出,所以插入位置为j-1+1
}
}
4.总结
- 插入排序的
i
从1开始,因为第0个数自己组成的数列是有序的 - 插入排序是稳定排序
- 对于随机排序的无重复主键的数列,插入排序和选择排序的运行时间是平方级别的,两者之比应该是较小的常数,且看后续文章详解
- 插入排序的时间取决于输入的数列,输入的序列有序性越高所消耗的时间就越少,插入排序经过优化就是希尔排序
- 选择排序属于初级排序,时间复杂度为 O(n2) ,当数据量较大时,建议采用高级排序