基于比较的插入排序-时间复杂度O(n^2)

直接插入排序(Insert Sort)

将数组中的数据分为两个区域,已排序区间和未排序区间。初始已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想就是取未排序区间中的元素,在已排序区间中从后往前找到最合适的位置将其插入,并保证已排序区间数据一直有序,重复这个过程,直到未排序区间中元素未空,算法结束。
在这里插入图片描述
以上插入排序也包含两种操作,元素比较和元素移动。当需要将数据 a 插入到已排序区间时,需要拿 a 与已排序区间元素依次比较大小,找到合适的位置,找到插入点之后还需要将插入点之后的元素往后移动才能腾出位置给元素 a。
在这里插入图片描述
对于不同的查找插入点方法(从头到尾、从尾到头),元素的比较次数是有区别的。但对于一个给定的初始序列,移动操作的次数总是固定的,就等于初始逆序度。如上图,满有序度是 n*(n-1)/2=15,初始序列的有序度是 5,所以逆序度是 10。插入排序中,数据移动的个数总和也等于 10=3+3+4。

// 插入排序,n表示数组大小
public void insertionSort(int[] arr, int n) {
    if (n < 1) {
        return;
    }
    
    for (int i = 1; i < n; i++) {
        // value 待插入的数
        int value = arr[i];
        // 插入的位置当然是从 i 前开始啦
        int j = i - 1;
        // 查找插入的位置
        for (; j >= 0; j--) {
            if (arr[j] > value) {
                arr[j+1] = arr[j]; // 数据移动
            } else {
                break;
            }
        } 
        a[j+1] = value;    // 插入元素
    }
}

小结:

  1. 插入排序是原地排序算法吗
    是,从实现过程可以明显看出,插入排序算法的运行并不需要额外的存储空间,所有空间复杂度是 O(1)
  2. 插入排序是稳定的排序算法吗?
    是,在插入排序中,对于值相同的元素,可以选择将后面出现的元素,插入到前面出现元素的后,这样 就可以保持原有的前后顺序不变。
  3. 插入排序的时间复杂度是多少?
    最好情况:元素是有序的,不需要搬移,只用从尾到头在有序数组里面找插入位置,每次只需要比较一 个数据就能确定插入位置。O(n)
    最坏情况:数组倒序,每次插入都相当于在数组的第一个位置插入新的数据,大量移动元素,O(n^2)
    平均时间复杂度:对于在数组中插入一个数据的平均时间复杂度是 O(n),对于插入排序,每次插入操作 都相当于在数组中插入一个数据,循环执行 n 次,所以平均时间复杂度是 O(n^2)
  4. 应用场景:数据规模小且接近有序
插入排序的优化—希尔排序

也称为缩小增量排序,与直接插入排序不同,会优先比较距离较远的元素。是把数据按一定的增量分组,对每组使用直接插入排序算法,随着增量逐渐减少,每组数越来越多,直到增量减至1,整个数组数据被分为一组,算法终止。
关于gap的取法其实是没有定论的,但是,大部分会在二分之一到三分之一附近。
在这里插入图片描述

详细代码:

public int[] ShellSort(int[] array) {
       int len = array.length;
       int temp, gap = len / 2;
       while (gap > 0) {
           for (int i = gap; i < len; i++) {
               temp = array[i];
               int preIndex = i - gap;
               while (preIndex >= 0 && array[preIndex] > temp) {
                   array[preIndex + gap] = array[preIndex];
                   preIndex -= gap;
               }
               array[preIndex + gap] = temp;
           }
           gap /= 2;
       }
       return array;
   }

小结:

  1. 应用场景:元素比较凌乱,个数比较多; 要求采用插入排序的思想对这个场景排序
    做法:将序列变成有序,将数据变少 ---->分组(gap/3+1)、平均分组、每组应用插入排序

  2. 算法的稳定性:不稳定,看一个排序算法是否稳定:该排序算法在进行的过程中是否跨元素进行交换或 插入,有则不稳定

  3. 空间复杂度:O(1);

  4. 时间复杂度:
    最好(数据有序) O(n)
    最坏(比较难构造) O(n^2)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值