插入排序原理
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。假设第一个元素排序之后,后面的元素对排号的部分从后向前比较并逐一移动。它包括直接插入排序、二分插入排序(又称折半插入排序)、链表插入排序、希尔排序(又称缩小增量排序),属于稳定排序的一种(稳定排序,通俗的讲,就是两个相等的数不会叫唤位置)。
下面介绍一下直接插入排序
直接插入排序
直接插入排序是一种简单的插入排序法,基本思想是:把待排序的记录按照其关键码值的大小逐一插入到一个已经排序过的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列。
例如,已知待排序的一组纪录是:
60,71,49,11,24,3,66
假设在排序过程中,前3个纪录已按关键码值递增的次序重新排列,构成一个有序序列:
49,60,71
将待排序纪录中的第4个纪录(即11)插入上述有序序列,以得到一个新的含4个纪录的有序序列。首先,应找到11的插入位置,再进行插入。可以讲11放入数组的第一个单元r[0]中,这个单元称为监视哨,然后从71起从右到左查找,11小于71,将71右移一个位置,11小于60,又将60右移一个位置,11小于49,又再将49右移一个位置,这时再将11与r[0]的值比较,11≧r[0],它的插入位置就是r[1]。假设11大于第一个值r[1]。它的插入位置应该在r[1]和r[2]之间,由于60已经右移了,留出来的位置正好留给11.后面的纪录依照同样的方法逐个插入到该有序序列中。若纪录数n,续进行n-1趟排序,才能完成。
直接插入排序的算法思路:
(1)设置监视哨r[0],将待插入纪录的值赋值给r[0];
(2)设置开始查找的位置j;
(3)在数组中进行搜索,搜索中将第j个纪录后移,直至r[0].key≥r[j].key为止;
(4)将r[0]插入r[j+1]的位置上。
iOS实现简单排序算法:
/*
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
*/
/// 插入排序
/// @param array 目标数组
-(void)insertSort:(NSMutableArray *)array
{
//插入排序的原理:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的
//移动数据,空出一个适当的位置,把待插入的元素放到里面去。
for (int i = 0; i < array.count; i++) {
id temp = array[i]; //temp 为待排元素 i为其位置 j为已排元素最后一个元素的位置(即取下一个元素,在已经排好序的元素序列中从后向前扫描)
int j = i - 1;
//当j < 0 时, i 为第一个元素 该元素认为已经是排好序的 所以不进入while循环
// [array[j] compare:temp] == NSOrderedDescending与[array[j] intValue] > [temp intValue] 作用相同
while (j > 0 && [array[j] doubleValue] > [temp doubleValue]) {
//如果已经排好序的序列中元素大于新元素,则将该元素往右移动一个位置
[array replaceObjectAtIndex:j+1 withObject:array[j]];
j--;
}
//跳出while循环时,j的元素小于或等于i的元素(待排元素)。插入新元素 i= j+1
[array replaceObjectAtIndex:j+1 withObject:temp];
}
}
稳定性:
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳定的。
算法复杂度:
如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次。平均来说插入排序算法的时间复杂度为O(n^2)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择。