排序算法3---插入排序
Posted 干货频道
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法3---插入排序相关的知识,希望对你有一定的参考价值。
前面我们分析了两种比较排序,冒泡排序和选择排序,这一节我们继续分析另一种比较排序---插入排序。
冒泡排序、选择排序都有比较操作和交换操作,而插入排序将交换操作优化为移动操作,没有对两个元素直接进行交换操作。交换操作有三次赋值,而移动操作只有一次赋值,这也正是插入排序优于冒泡排序的原因。
插入排序的核心操作就是将一个数据插入到已经排好序的有序组中,得到一个新的,个数加1的有序组,相应的无序组个数减1。
算法原理
将原始数组分为有序组(第一个元素)和无序组(剩下的 N-1 个元素);
从无序组取出第一个元素作待插入元素,在有序组中从后向前比较,将比待插入元素大的数据向后移动一个位置,重复操作,直到碰到小于或等于待插入元素的数据,然后将待插入元素插入此位置;
重复上一步,直到整个数组变为有序组。
算法分析
下面用从网上选的一个动图来分析插入排序,个人觉得这个动图非常形象、直观,可以让我们很容易的理解插入排序的原理。
注:下图选自网络,在此感谢此图作者。
分析:从上面的动画我们可以看出整个数组被分为两部分,一部分是有序组用黄色标识,一部分是无序组用蓝色标识(第一次循环,第一个数据作有序组,剩下 N-1 个数据作无序组)。每次从无序组取出第一个元素,然后从有序组的后面向前面比较,将比待插入元素大的数据向后移动,直到碰到小于或等于待插入元素的数据,最后将待插入元素插入相应位置。重复以上操作,有序组个数不断加一,无序组个数不断减一,直到所有元素成为有序组。
算法实现
根据上面的排序分析,我们实现以下算法。
// 插入排序
void insertion_sort(int *arr, int n)
{
int i = 0, j = 0;
int val = 0;
for(i=1; i<n; i++)
{
val = arr[i];
j = i - 1;
while( j >= 0 && arr[j] > val )
{
arr[j+1] = arr[j];
j--;
}
arr[j+1] = val;
}
}
算法改进
插入排序从后向前比较,每次数据只能移动一个位置,这样效率比较低,后来有人就在这个步进上做文章,提出了“缩小增量排序”,这个人就是希尔,因此得名希尔排序。后面我们用单独一节来分析希尔排序。
算法性能
时间复杂度
插入排序的平均时间复杂度为o(n2),最优时间复杂度为o(n),最差时间复杂度为o(n2)。
空间复杂度
插入排序的空间复杂度为 o(1)。每次从无序组中取出待插入有序组的元素,需要开辟一个空间存放此待插入元素,与数组规模无关,所以插入排序的空间复杂度为o(1)。
稳定性
插入排序是一种稳定的排序算法。插入排序是从后向前比较,按需移动位置,然后插入,如果有两个相等的元素时,上述操作不会改变相同元素的前后顺序,因此插入排序是稳定的。
github源码连接:https://github.com/yqwung/sort
以上是关于排序算法3---插入排序的主要内容,如果未能解决你的问题,请参考以下文章