数据结构与算法八: 1)排序算法--直接插入排序

349 阅读3分钟

这是我参与8月更文挑战的第6天,活动详情查看:8月更文挑战

关注我,以下内容持续更新

数据结构与算法(一):时间复杂度和空间复杂度

数据结构与算法(二):桟

数据结构与算法(三):队列

数据结构与算法(四):单链表

数据结构与算法(五):双向链表

数据结构与算法(六):哈希表

数据结构与算法(七):树

数据结构与算法(八):排序算法

数据结构与算法(九):经典算法面试题

排序的分类

  1. 插入排序: 直接插入排序 希尔排序
  2. 交换排序: 冒泡排序 快速排序
  3. 选择排序: 简单选择排序 堆排序
  4. 归并排序

本篇主要讲解直接插入排序

直接插入排序

插入排序的主要操作是插入. 核心:在插入第i(i>1)个元素时,前面的 i-1 个元素已经排好.

基本思想:把n个待排序的元素看成为一个有序表和一个无序表,初始状态将第一个元素看成是初始有序表,无序表中包含有后边的n-1个元素,排序过程中每次从无序表中取出第一个元素,把它的排序码依次与有序表元素的排序码进行比较,将它插入到有序表中的适当位置,使之成为新的有序表。

代码实现:双层循环,首先假设array[0]已经排好序,第一层循环从array[1]开始,每次内层循环都是array[i]和有序表中的元素依次比较,找到合适的位置就插入,也就是前边的元素如果比自己大,那么前边的元素往后移,否则就找到正确的位置,停止本轮内层循环,插入到此位置。每轮循环走完后都可以保证i左边的元素是有序的。

图示.png

插入排序有交换法和移位法,用移位法效率更好,因为减少了交换次数。

//2.1 插入排序--移位法 (while 循环 实现)
-(void)insertSort:(NSMutableArray*)arr{
    for (int i = 1; i<arr.count; i++) {
        int tmp = [arr[i] intValue];//当前值是要比较的值
        int j = i;//j代表要插入的位置,tmp要和 j-1 比较,如果tmp大,则插入到j-1后面的位置,就是 j

        while (j>0 && tmp < [arr[j-1] intValue]) {
            arr[j] = arr[j-1];//前边的元素往后移动一位
            j--;//循环
        }
        arr[j] = @(tmp);//把要比较的元素插入在正确的位置
    }
}
//2.1 插入排序---移位法 (for循环实现)
-(void)insertSort:(NSMutableArray*)arr{
    for (int i = 1; i<arr.count; i++) {
        //暂存arr[i]的值,也就是要插入的值,使其不至于因为元素的后移而丢失元素的内容
        int tmp = [arr[i] intValue];
        int j = i;
        for (;j>0; j--) {//j代表要插入的位置,tmp要和j的前一个位置比较,如果符合顺序就停止循环直接插入到j
            if (tmp < [arr[j-1] intValue]) {//如果tmp比前边的小,继续循环,并把arr[j-1]后移
                arr[j] = arr[j-1];//前边的元素往后移动一位
            }else{//如果遇到正确的位置,并退出循环;因为for循环的条件是>0,所以退出循环后,再插入到正确的位置
                break;
            }
        }
        arr[j] = @(tmp);//直接插入到j
    }
}
//2.2 插入排序 -- 交换法 (性能差,每次比较都交换)

-(void)insertSort:(NSMutableArray*)arr{

    for (int i = 1; i<arr.count; i++) {

        for (int j = i; j>0; j--) {

            if ([arr[j] intValue] < [arr[j-1] intValue]) {

                NSNumber*tmp = arr[j];

                arr[j] = arr[j-1];

                arr[j-1] = tmp;

            }

        }

    }

}

性能分析

直接插入排序性能分析:

  • 最好情况下(正序):

    比较次数 n-1;移动次数 2(n-1),时间复杂度为 o(n)

  • 最坏情况下(逆序):

    比较次数 n-1;移动次数 2(n-1),时间复杂度为 o(n²)

  • 平均情况下(随机序列):

    时间复杂度为 o(n²)

另外,还需要一个记录的辅助空间来暂存要插入的元素,防止元素的后移而丢失元素的内容

直接插入排序的优化

直接插入排序算法简单,容易实现,适用于基本有序的序列或个数较少的序列,当待排序的元素较多时,大量的比较和移动会导致性能降低.

优化方向1: 在插入第i(i>1)个元素时,前面的 i-1 个元素已经排好,在查找插入位置时,可以用二分查找来代替顺序查找,从而减少比较次数.

优化方向2:当较小的数在序列的偏后面的位置时,后移的次数明显增多,对效率有影响。针对这一点,希尔排序做出了优化,通过设置一个增量gap,使得序列基本有序.

其他排序算法

排序算法:1)直接插入排序

排序算法:2)希尔排序

排序算法:3)冒泡排序

排序算法:4)快速排序

排序算法:5)选择排序

排序算法:6)归并排序

排序算法:7)基数排序

排序算法:8)堆排序

关注我

如果觉得我写的不错,请点个赞 关注我 您的支持是我更文最大的动力!