iOS-插入排序

序言

以下内容摘自百度百科 插入排序

有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外(让数组多一个空间才有插入的位置),而第二部分就只包含这一个元素(即待插入元素)。在第一部分排序完成后,再将这个最后元素插入到已排好序的第一部分中。

插入排序的基本思想是:每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

总结:插入排序法(Inser Sort)是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序。

算法思想
  • ⒈ 从第一个元素开始,该元素可以认为已经被排序
  • ⒉ 取出下一个元素,在已经排序的元素序列中从后向前扫描
  • ⒊ 如果该元素(已排序)大于新元素,将该元素移到下一位置
  • ⒋ 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  • ⒌ 将新元素插入到下一位置中
  • ⒍ 重复步骤2~5

范例代码

/**
 插入排序
 
 @param array 需要排序的Array
 */
- (void)inserSort:(NSMutableArray *)array{
    // 插入排序的原理:始终定义第一个元素为有序的,将元素逐个插入到有序排列之中,其特点是要不断的
    
    // 移动数据,空出一个适当的位置,把待插入的元素放到里面去。
    for (int i = 0; i < array.count; i++) {
        
        NSNumber *temp = array[i];
        // temp 为待排元素 i为其位置 j为已排元素最后一个元素的位置(即取下一个元素,在已经排好序的元素序列中从后向前扫描)
        
        int j = i-1;
        
        // 当j < 0 时, i 为第一个元素 该元素认为已经是排好序的 所以不进入while循环
        while (j >= 0 && [array[j] intValue] > [temp intValue]) {
            //如果已经排好序的序列中元素大于新元素,则将该元素往右移动一个位置
            [array replaceObjectAtIndex:j+1 withObject:array[j]];
            j--;
        }
        // 跳出while循环时,j的元素小于或等于i的元素(待排元素)。插入新元素 a[j+1] = temp,即将空出来的位置插入待排序的值
        [array replaceObjectAtIndex:j+1 withObject:temp];
        NSLog(@"插入排序排序中:%@",[self getArrayStr:array]);
    }
}

// 将数组中的元素拼接成字符串 - 方便打印
- (NSString *)getArrayStr:(NSArray *)array {
    NSMutableString *strM = [NSMutableString string];
    for (NSNumber *num in array) {
        [strM appendString:[NSString stringWithFormat:@"%@,",num]];
    }
    return strM.copy;
}

排序

NSArray *array = @[@3,@2, @6, @9, @8, @5, @7, @1, @4];
[self inserSort:[NSMutableArray arrayWithArray:array]];

打印结果

《iOS-插入排序》 image.png

由打印结果可知,一共遍历了9次,最终完成数组排序。

二 算法分析
  • 直接插入排序的算法性能

《iOS-插入排序》 image.png

  • 时间复杂度
    当元素的初始序列为正序时,仅外循环要进行n-1趟排序且每一趟只进行一次比较,没有进入if语句不存在元素之间的交换(移动)。此时比较次数(Cmin)和移动次数(Mmin)达到最小值。 此时时间复杂度为O(n)
Cmin = n-1;
Mmin = 0;

当元素的初始序列为反序时,每趟排序中待插入的元素都要和[0,i-1]中的i个元素进行比较且要将这i个元素后移(arr[j+1] = arr[j]),i个元素后移移动次数当然也就为i了,再加上temp = arr[i]与arr[j+1] = temp的两次移动,每趟移动的次数为i+2,此时比较次数(Cmin)和移动次数(Mmin)达到最小值。 此时时间复杂度为O(n2)。

Cmax = 1+2+...+(n-1) = n*(n-1)/2 = O(n2)
Mmax = (1+2)+(2+2)+...+(n-1+2) = (n-1)*(n+4)/2 = O(n2)  (i取值范围1~n-1)

数据越接近正序,直接插入排序的算法性能越好。

  • 空间复杂度
    由直接插入排序算法可知,我们在排序过程中,需要一个临时变量存储要插入的值,所以空间复杂度为 O(1) 。

  • 算法稳定性
    直接插入排序的过程中,不需要改变相等数值元素的位置,所以它是稳定的算法。

三 插入排序和选择排序的区别
  • 插入排序和选择排序都有两层循环,外循环遍历整个数组

  • 内循环稍有区别:

    • 选择排序的内循环是遍历一组未排过序的数组。
    • 插入排序的内循环是遍历一组已排过序的数组。

本文参考

排序三 直接插入排序

项目连接地址 – InsertSortDemo

    原文作者:路飞_Luck
    原文地址: https://www.jianshu.com/p/0a55c7e2857c
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞