排序算法-插入排序的时间复杂度分析

插入排序的原理是,将数组分为已排序区间和未排序区间两部分,从未排序区间中依次取元素跟已排序区间的元素一一对比,找到适合插入的位置。

拿数组[4,5,6,1,3,2]来举例,如图所示是排序的图解过程。这个过程比上边的原理详细的多,本以为可以按照原理来写出插入排序的代码,尝试了几次发现原理的信息量并不足以写出来。这里边最难理解的就是当已排序区间元素发现比未排序区间元素大的时候,已排序区间的元素会往后移动一位,然后已排序区间待比较元素继续往前移动进行比较,如果发现比未排序区间元素还大,继续往后移动一位,最终若已排序区间的元素是一个比未排序区间的元素小停止比较,把这个未排序区间元素赋值给那个已排序区间相对比较是小的元素的下一位。

怎么样?是不是被我绕晕了。结合下边这个图和代码思考一下吧!

我觉得还是要回归到数据结构本身,这里使用的是数组的排序,使用到比较和移动,比较比较简单,所以关键在于如何移动?

很遗憾,这里把整个处理搞明白之后才理解到这一层,那就是根据数据结构本身的特点,思考如何操作,比如数组就思考如何移动才能满足算法的需要(比如这里的插入排序)

对于任何数据结构和算法的学习,要充分理解数据结构本身的特点以及熟练数据结构的各种操作(比较、移动方式等)。

这里也就是没充分理解插入排序算法中数据的移动原理。

 

插入排序代码:

 /**
     *  插入排序,a 表示数组,n 表示数组大小
     * @param n
     */
    public static void insertionSort(int[] a, int n) {
        if (n <= 1){
            return;
        }

        for (int i = 1; i < n; ++i) {
            int value = a[i];
            int j = i - 1;
            // 查找插入的位置
            for (; j >= 0; --j) {
                if (a[j] > value) {
                    // 数据移动
                    a[j+1] = a[j];
                } else {
                    break;
                }
            }
            // 插入数据
            a[j+1] = value;
        }
    }

 

插入排序是原地排序算法吗?

所谓原地排序算法,就是空间复杂度为O(1)的算法,那么上边的算法不牵涉额外得到其他空间。所以是原地排序算法。

 

插入排序是稳定排序算法吗?

所谓稳定,指的是当数组中出现相同数值元素的时候,排序是否会造成相同数值元素相对位置的改变。可以看出在插入排序算法中,对于相同数值的元素可以选择插入到已排序区间等值元素的后边,所以相同数值元素的相对位置不会发生改变,因此插入排序算法是稳定的排序算法。

 

插入排序算法的时间复杂度是多少?

在完全有序的情况下,插入排序每个未排序区间元素只需要比较1次,所以时间复杂度是O(n)。而在极端情况完全逆序,时间复杂度为O(n^2).就等于每次都把未排序元素插入到数组第一位。在数组中插入1个元素的时间复杂度为O(n),那插入n个就是o(n^2)了。(对于一个给定的初始序列,移动操作的次数总是固定的,就等于逆序度。)

 

插入排序与冒泡排序对比

其实插入排序的移动操作比冒泡排序简单很多,插入排序需要一个赋值操作,冒泡要三个,如果较真点看首选还是插入排序,因为插入排序不但移动操作简单,而且优化空间还很大。这篇这个只是基本的一种。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jeff.sheng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值