为什么插入排序是使用频率最高的排序算法?

想象你在玩麻将或扑克,每次抽牌后都会把新牌插入到手中已经排好序的牌堆中。这个直观的过程与插入排序算法很像。

在插入排序中,初始状态下我们假定数组的第一个元素是已排序的,从第二个元素开始,将每个元素依次插入到正确的位置,重复这个过程,直至数组完全有序。

插入排序操作的核心在于两点:比较移动

通过比较,我们能够确定新元素的插入点;通过移动,我们为新元素的插入腾出空间。

插入排序复杂度分析

在最坏情况下,即数组完全逆序,第 n 个元素可能需要与前面所有 n-1 个元素比较才能找到自己的位置,比较次数达到 1+2+3+...+n-1 = (n-1)(n)/2 次,复杂度为 O(n^2)

同样地,移动操作此时也是如此。插入第 n 个元素,需要移动 n-1 个元素,因此总的移动次数也是 O(n^2)

然而,在最佳情况下,即数组已经有序,插入排序则非常高效,每次仅需进行一次比较,总比较次数为 n-1 次,复杂度为 O(n),而且无需移动任何元素。

插入排序优势

虽然插入排序的理论时间复杂度为 O(n^2),并不如 O(nlogn) 的高效排序算法,但得益于其简洁的操作,在小规模数据集上的表现通常非常出色。

快速排序等 O(nlogn) 级别的算法,虽然在大规模数据集上效率高,但涉及的基本操作更多。当处理的数据量小的时候,n^2nlogn 之间的差距不大,复杂度不占主导作用,每轮的单元操作数量起到决定性因素。

现在来看看简洁的插入排序算法的实现:

python 复制代码
def insertion_sort(arr):

    for i in range(1, len(arr)):
        val = arr[i]
        j = i - 1

        while j >= 0 and arr[j] > val:
            arr[j + 1] = arr[j]  # move
            j -= 1
        arr[j + 1] = val  # insert

源代码:insertionsort01

插入排序中确定的移动次数

这里有一个有趣的结论:插入排序中移动元素的次数与数组中逆序对的数量相等。

这个结论初看上去不太好理解,我们考虑一个数组 [4,2,3,1],从中可以找出以下六个数据对:(4,2)(4,3)(4,1)(2,3)(2,1)(3,1)

在这些数据对中,除了 (2,3) 是正序对之外,其他都是逆序对。

  • 当数字 2 被处理时,它移动到 4 的前面,消除了逆序对 (4,2)
  • 当数字 3 被处理时,它移动到 4 的前面,消除了逆序对 (4,3)
  • 当数字 1 被处理时,它移动到每一个数字的前面,消除了逆序对 (4,1)(3,1)(2,1)

每次移动都改变了两个逆序的元素的位置,相当于减少了一个逆序对。

因此对于一个给定的数组,移动的总次数在插入排序开始前就已经固定了。

插入排序的优化

既然移动次数是固定的,那么我们可以尝试从减少比较次数的角度来优化插入排序。

在插入排序中,数据被分为已排序部分和未排序部分。在已排序部分,我们寻找未排序部分下一个元素的正确位置时,通常会用到线性查找。

然而,一个优化手段是利用二分查找法,在已排序的序列中寻找插入点。

通过这种方式,我们可以将单次插入的比较次数降至 O(log n),总的比较次数减少至 O(nlog n)。然而,由于移动操作的次数保持不变,整个算法的时间复杂度仍为 O(n^2)

尽管如此,对于小规模的数据集而言,这样的优化是有益的,可以明显提高排序效率。

插入排序的一个重要特性是其稳定性。例如,在序列 [4a, 4b, 3, 5] 中,即使 4a4b 的值相等,它们在排序后也应保持原有顺序。

使用普通的二分查找可能会破坏这一稳定性,因为它可能会无视相同元素的原始顺序。

为了维护稳定性,我们对二分查找进行调整,确保遇到相等元素时总是将搜索范围移至右侧。 这保证了我们可以定位到相等元素中最右侧的位置,并将新元素插入其后。

采用这种方法,我们可以得到一种稳定的二分插入排序算法(stable binary insertion sort)

稳定的二分插入排序算法代码实现:

python 复制代码
def binary_search(arr, val, start, end):
    while start <= end:
        mid = (start + end) // 2
        if arr[mid] < val:
            start = mid + 1
        elif arr[mid] > val:
            end = mid - 1
        else:  # arr[mid] == val
            start = mid + 1  # move to right for stability

    return start

def insertion_sort(arr):
    for i in range(1, len(arr)):
        selected = arr[i]
        j = i - 1

        # find location where selected should be inserted
        loc = binary_search(arr, selected, 0, j)

        # Move all elements after location to create space
        while j >= loc:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = selected

源代码:insertionsort02

总结

优化后的算法,以其在处理小型数据集时的卓越性能,已被集成到 TimSort 复合排序算法中。考虑到 TimSort 是众多编程语言默认的 sort() 方法算法,这种稳定的二分插入排序算法可能是世界上应用最普遍的排序算法之一。

更多内容请关注我的公众号:dingtingli

WWH 系列文章列表:

1\] [Why - 为什么 JS 更像一门编译型语言?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454608234%26idx%3D1%26sn%3D5b2b7c62d18f01ce5dfa7607bc86a12b%26chksm%3Dfbf0b331cc873a275a5f3d42081549feb668e9d1beea7ce78125c0a547728a9cb262ff266194%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454608234&idx=1&sn=5b2b7c62d18f01ce5dfa7607bc86a12b&chksm=fbf0b331cc873a275a5f3d42081549feb668e9d1beea7ce78125c0a547728a9cb262ff266194&scene=21#wechat_redirect") \[2\] [What - 什么是依赖注入?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454608405%26idx%3D1%26sn%3D5237d417b8a7d26ff11a7fea13c42f3d%26chksm%3Dfbf0b04ecc873958d4c0764d0bf2552da9ebd36cac39b4222af1c47fcca562b8a772561146fb%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454608405&idx=1&sn=5237d417b8a7d26ff11a7fea13c42f3d&chksm=fbf0b04ecc873958d4c0764d0bf2552da9ebd36cac39b4222af1c47fcca562b8a772561146fb&scene=21#wechat_redirect") \[3\] [What - 什么是 Big O?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454608780%26idx%3D1%26sn%3Dcc5a66e5653f05834a987deb805a0a01%26chksm%3Dfbf0b1d7cc8738c1b31566dcbb3daf5de950da27df4258cac0b800081b0748f6ae0f90b945b1%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454608780&idx=1&sn=cc5a66e5653f05834a987deb805a0a01&chksm=fbf0b1d7cc8738c1b31566dcbb3daf5de950da27df4258cac0b800081b0748f6ae0f90b945b1&scene=21#wechat_redirect") \[4\] [How - 不同的语言都如何处理错误?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609524%26idx%3D1%26sn%3D49a447dd1cef64fcd1f31878a954d216%26chksm%3Dfbf0b42fcc873d39c1b5734856980b9cb1dbccbdd0be93b65bce7c627454e3f464a6682241ff%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609524&idx=1&sn=49a447dd1cef64fcd1f31878a954d216&chksm=fbf0b42fcc873d39c1b5734856980b9cb1dbccbdd0be93b65bce7c627454e3f464a6682241ff&scene=21#wechat_redirect") \[5\] [How - 面向对象语言如何处理异常?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609526%26idx%3D1%26sn%3Dfba1299fe5eb1263e7fffafe46efe747%26chksm%3Dfbf0b42dcc873d3b0e380429796733109f9b031e0e0bd566f7267746fa49091ba60b2b7ccbea%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609526&idx=1&sn=fba1299fe5eb1263e7fffafe46efe747&chksm=fbf0b42dcc873d3b0e380429796733109f9b031e0e0bd566f7267746fa49091ba60b2b7ccbea&scene=21#wechat_redirect") \[6\] [Why - 为什么排序算法复杂度上限是 O(NlogN)?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609763%26idx%3D1%26sn%3D73eebf3a295e0d01ae75da17b5ec13b4%26chksm%3Dfbf0b538cc873c2e812fb71fb9316d9ec94d0e03c95847f36599cc0a16c4ccfc15b8ceda4d2a%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609763&idx=1&sn=73eebf3a295e0d01ae75da17b5ec13b4&chksm=fbf0b538cc873c2e812fb71fb9316d9ec94d0e03c95847f36599cc0a16c4ccfc15b8ceda4d2a&scene=21#wechat_redirect") 最近文章列表: \[1\] [在 C 语言中实现简单的哈希表](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609495%26idx%3D1%26sn%3D81c673d290296473614ec7692f771430%26chksm%3Dfbf0b40ccc873d1aebe70d42fadf30070f0e0b7ed411cfffcec35eb50755715d748d60db3a7b%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609495&idx=1&sn=81c673d290296473614ec7692f771430&chksm=fbf0b40ccc873d1aebe70d42fadf30070f0e0b7ed411cfffcec35eb50755715d748d60db3a7b&scene=21#wechat_redirect") \[2\] [成就卓越:事业成功的核心要素](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609503%26idx%3D1%26sn%3De81a7ba74839984e54cfe4f7486d18a7%26chksm%3Dfbf0b404cc873d12d47f3cae76755c0d43c3be53dd07bce4ccab7d52fd9d4aa93dc0b67b24fa%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609503&idx=1&sn=e81a7ba74839984e54cfe4f7486d18a7&chksm=fbf0b404cc873d12d47f3cae76755c0d43c3be53dd07bce4ccab7d52fd9d4aa93dc0b67b24fa&scene=21#wechat_redirect") \[3\] [C++异常处理的底层机制](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609673%26idx%3D1%26sn%3Df8d2de7717b42af2a8556b052579b90a%26chksm%3Dfbf0b552cc873c445fbf05973e0720000bf139710ec2fa65008c38c912439020effb3a3964c3%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609673&idx=1&sn=f8d2de7717b42af2a8556b052579b90a&chksm=fbf0b552cc873c445fbf05973e0720000bf139710ec2fa65008c38c912439020effb3a3964c3&scene=21#wechat_redirect") \[4\] [.git 目录里到底包含了什么?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609762%26idx%3D1%26sn%3D2d3b08cfd88beec29f27bb501f115cc8%26chksm%3Dfbf0b539cc873c2f62df9f5ebf17568957187584ccf3d982958bd2ab87c624e2784e39223391%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609762&idx=1&sn=2d3b08cfd88beec29f27bb501f115cc8&chksm=fbf0b539cc873c2f62df9f5ebf17568957187584ccf3d982958bd2ab87c624e2784e39223391&scene=21#wechat_redirect") \[5\] [看图聊算法:一个游戏让你理解二分法的本质](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609685%26idx%3D1%26sn%3D789b352a289ee9a9a5a0395448fbc0b3%26chksm%3Dfbf0b54ecc873c580fdf833e4ba6aba29771c78bc26ecca5dee7245e819e49de962aee39c35a%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609685&idx=1&sn=789b352a289ee9a9a5a0395448fbc0b3&chksm=fbf0b54ecc873c580fdf833e4ba6aba29771c78bc26ecca5dee7245e819e49de962aee39c35a&scene=21#wechat_redirect") \[6\] [看图聊算法:超越二分法,探索大厂经典面试题](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609698%26idx%3D1%26sn%3D7a65dc149f2c1da8ebc15e91e7d17f43%26chksm%3Dfbf0b579cc873c6f6637ceb38c800865ca5f1e36f087940a629c104ef4fc272b79b5b3dd925e%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609698&idx=1&sn=7a65dc149f2c1da8ebc15e91e7d17f43&chksm=fbf0b579cc873c6f6637ceb38c800865ca5f1e36f087940a629c104ef4fc272b79b5b3dd925e&scene=21#wechat_redirect") \[7\] [看图聊算法:插入排序,使用频率最高的排序算法](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609789%26idx%3D1%26sn%3D4a3a2c271c6addb6cbbf92abbaed3893%26chksm%3Dfbf0b526cc873c309dc1384d09359032028bc176bc71166214a42103b3a526d601dd2849b46c%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609789&idx=1&sn=4a3a2c271c6addb6cbbf92abbaed3893&chksm=fbf0b526cc873c309dc1384d09359032028bc176bc71166214a42103b3a526d601dd2849b46c&scene=21#wechat_redirect") \[8\] [看图聊算法:归并排序的原理与优化](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609846%26idx%3D1%26sn%3D1e2ea7ab24c5de0e70fb4e474bf8b1dc%26chksm%3Dfbf0b5edcc873cfb2858ef544bc6cdb2eec5f1400b1355dfedd02aaae4cc586b399a45941bff%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609846&idx=1&sn=1e2ea7ab24c5de0e70fb4e474bf8b1dc&chksm=fbf0b5edcc873cfb2858ef544bc6cdb2eec5f1400b1355dfedd02aaae4cc586b399a45941bff&scene=21#wechat_redirect") \[9\] [看图聊算法:冯·诺依曼的第一个计算机程序](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609864%26idx%3D1%26sn%3Ddc220fb01afba6abba6940e87d75a4fc%26chksm%3Dfbf0b593cc873c85d2cfca6fb318b71a129f55e3a2ed3a67181dbeff062b7fe8e9d47418687c%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609864&idx=1&sn=dc220fb01afba6abba6940e87d75a4fc&chksm=fbf0b593cc873c85d2cfca6fb318b71a129f55e3a2ed3a67181dbeff062b7fe8e9d47418687c&scene=21#wechat_redirect") \[10\] [看图聊算法:快速排序为什么快?](https://link.juejin.cn?target=http%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzI5NjA1MDQ4NA%3D%3D%26mid%3D2454609959%26idx%3D1%26sn%3Da5889e55d4fd4f03f912880f7b0aa589%26chksm%3Dfbf08a7ccc87036aba727418ffa30d2a9d5a4c569ac5b71b806a719ba2f7fc45729ddca4b98f%26scene%3D21%23wechat_redirect "http://mp.weixin.qq.com/s?__biz=MzI5NjA1MDQ4NA==&mid=2454609959&idx=1&sn=a5889e55d4fd4f03f912880f7b0aa589&chksm=fbf08a7ccc87036aba727418ffa30d2a9d5a4c569ac5b71b806a719ba2f7fc45729ddca4b98f&scene=21#wechat_redirect") **更多内容请关注我的公众号:dingtingli**

相关推荐
天上路人1 小时前
AI神经网络降噪算法在语音通话产品中的应用优势与前景分析
深度学习·神经网络·算法·硬件架构·音视频·实时音视频
好吃的肘子1 小时前
MongoDB 应用实战
大数据·开发语言·数据库·算法·mongodb·全文检索
汉克老师1 小时前
GESP2025年3月认证C++二级( 第三部分编程题(1)等差矩阵)
c++·算法·矩阵·gesp二级·gesp2级
sz66cm1 小时前
算法基础 -- 小根堆构建的两种方式:上浮法与下沉法
数据结构·算法
緈福的街口1 小时前
【leetcode】94. 二叉树的中序遍历
算法·leetcode
小刘要努力呀!2 小时前
嵌入式开发学习(第二阶段 C语言基础)
c语言·学习·算法
野曙3 小时前
快速选择算法:优化大数据中的 Top-K 问题
大数据·数据结构·c++·算法·第k小·第k大
Codeking__3 小时前
”一维前缀和“算法原理及模板
数据结构·算法
休息一下接着来3 小时前
C++ 条件变量与线程通知机制:std::condition_variable
开发语言·c++·算法
Code哈哈笑3 小时前
【机器学习】支持向量回归(SVR)从入门到实战:原理、实现与优化指南
人工智能·算法·机器学习·回归·svm