插入排序算法

原理

  1. 把所有的元素分为两组,已经排序的和未排序的。
  2. 找到未排序的组中的第一个元素,向已经排序的组中进行插入。
  3. 倒序遍历已经排序的元素,依次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素,那么就把待插入元素排到这个元素后面。

动图演示如下,其中绿色表示已经排序的元素,红色表示未排序元素。
插入排序gif

时间复杂度

最好情况:如果待排序数组一开始就是顺序的,那么只要检查一下外层循环,不需要进行内层循环,此时时间复杂度为T = O(n)。
最坏情况:待排序数组一开始就是逆序的,那么每次内循环都要走一遍,此时时间复杂度为T = O(n^2)。
平均:T = O(n^2)。

排序稳定性

只交换比待排序元素大的元素,所以插入排序是稳定的。

优缺点

优点:和冒泡类似,代码实现简单。对于差不多排好序的数组时间复杂度接近O(n)。
缺点:平均时间复杂度达到了O(n^2)。

代码实现

我这里使用的是C#来实现,提供两种版本
下面这个是比较好理解的版本

    public static void InsertionSort(ref int[] needSortAarray)
    {
        // 插入排序外层循环从1开始
        for (int i = 1; i < needSortArray.Length; ++i)
        {
            int insertIndex = i;
            // 倒序遍历已经排序好的元素
            for (int j = i - 1; j >= 0; --j)
            {
            	// 如果排好序的元素中存在比待插入元素大的情况
            	// 交换位置
                if (needSortArray[insertIndex] < needSortArray[j])
                {
                    Swap(ref needSortArray[insertIndex], ref needSortArray[j]);
                    insertIndex = j;
                }
                else
                {
                	// 这步走进来,说明此时待插入元素已经到达正确的位置
                	// 可以提前退出循环
                    break;
                }
            }
        }
    }

难理解的版本

        public static void InsertionSort(ref int[] arr)
        {
            // 默认第一张牌就是在手中的,所以i从1开始作为arr[i]作为插入元素
            for (int i = 1; i < arr.Length; i++)
            {
                int temp = arr[i];
                int j = i;

                // 如果插入元素前面的元素都大于待插入的元素,那么都往后移动一位。
                for (; j > 0 && arr[j - 1] > temp; j--)
                {
                    arr[j] = arr[j - 1];
                }

                // 条件不满足时,说明此时j是待插入元素正确的位置。
                // 同时存在如果上面循环没有执行的话,此时arr[j]就是arr[i],下面这步是多余的。
                arr[j] = temp;
            }
        }

总结

插入排序和冒泡排序一样也是一种很简单的排序算法,在一些现代编程语言内部库提供的Sort方法中一般是用两种算法组合的方式,n如果数量比较小会使用插入排序,如果n数量比较大时会使用快速排序。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值