在归并排序中对小数组采用插入排序

摘要: 使递归的叶子变粗

【对算法,数学,计算机感兴趣的同学,欢迎关注我哈,阅读更多原创文章】

我的网站:潮汐朝夕的生活实验室

我的公众号:算法题刷刷

我的知乎:潮汐朝夕

我的github:FennelDumplings

我的leetcode:FennelDumplings


在文章 分治算法的设计与分析-归并排序 中,我们了解了分治算法的设计和分析方法,并且得出了归并排序算法的最坏情况运行时间为 Θ ( n log ⁡ n ) \Theta(n\log n) Θ(nlogn)。

在文章 基于随机访问机模型分析算法 中,我们了解了算法分析的方法论,并且以插入排序为例,得到了插入排序最坏情况运行时间为 Θ ( n 2 ) \Theta(n^{2}) Θ(n2)。

虽然开起来好像归并排序比插入排序的运行时间要好,但插入排序中的常量因子可能使得它在 n 较小时,在许多机器上实际运行得更快。因此归并排序中,当子问题规模足够小时,采用插入排序使得递归的叶变粗是有意义的。

本文我们来分析一下,子问题规模多小的时候采用插入排序,可以取得收益。

问题描述

考虑长度为 n 的数组,使用插入排序来排序长度为 k k k 的 n k \frac{n}{k} kn 个子表,然后用归并排序的合并机制来合并这些子表。

分析这个算法的运行时间,与归并排序进行对比,并研究实践中选择 k 的策略。

排序 n / k n/k n/k 个子表的运行时间

插入排序一个长为 k k k 的数组,最坏情况的运行时间为 Θ ( k 2 ) \Theta(k^{2}) Θ(k2),于是排序 n k \frac{n}{k} kn 个子表的运行时间为:

Θ ( k 2 ) × n k = Θ ( n k ) \Theta(k^{2}) \times \frac{n}{k} = \Theta(nk) Θ(k2)×kn=Θ(nk)

合并 n / k n/k n/k 个子表的运行时间

合并 K K K 个已排序的数组(链表),每个已排序数组长度为 N N N,合并后总长度为 K N KN KN。在 力扣23-合并K个升序链表 中我们解决过这个问题,有堆和分治两种方法,运行时间一样。分析过程如下:

如果用堆的方法,堆的容量为 K K K,因此堆的插入删除运行时间 Θ ( log ⁡ K ) \Theta(\log K) Θ(logK),而 K K K 个已排序数组的总长度为 K N KN KN,因此总的运行时间为: Θ ( K N log ⁡ K ) \Theta(KN\log K) Θ(KNlogK)。

如果用分治法,过程如下:

  • 分解:将 K K K 个已排序数组分为两份,每份 K / 2 K / 2 K/2 个
  • 解决:如果 K = 1 K = 1 K=1,可以直接解决,运行时间 Θ ( 1 ) \Theta(1) Θ(1)
  • 合并:将两个有序数组合并为 1 个

按照以上流程,每一轮合k并 K 2 \frac{K}{2} 2K 组链表,每一组 2 个,因此每组运行时间为 Θ ( 2 N ) \Theta(2N) Θ(2N);每二轮合并 k 4 \frac{k}{4} 4k 组链表,每一组 4 个,因此每组运行时间为 Θ ( 4 N ) \Theta(4N) Θ(4N),以此类推,总运行时间为 Θ ( ∑ i = 1 log ⁡ K K 2 i × 2 i N ) = Θ ( K N log ⁡ K ) \Theta(\sum\limits_{i=1}\limits^{\log K}\frac{K}{2^{i}}\times 2^{i}N) = \Theta(KN\log K) Θ(i=1∑logK2iK×2iN)=Θ(KNlogK)。

这里我们是要合并 n k \frac{n}{k} kn 个已排序数组,每个的长度为 k k k,合并后总长度 n n n,因此合并的运行时间为 Θ ( n log ⁡ n k ) \Theta(n\log \frac{n}{k}) Θ(nlogkn)。

整体的运行时间

在归并排序中,对小数组用插入排序,分为排序 n / k n/k n/k 个子表,合并 n / k n/k n/k 个子表两步,前面分别分析了这两步的运行时间,因此总运行时间为:

Θ ( n k ) + Θ ( n log ⁡ n k ) = Θ ( n k + n log ⁡ n k ) = Θ ( n log ⁡ n + n k − n log ⁡ k ) = Θ ( n log ⁡ n + n ( k − log ⁡ k ) ) \begin{align} \Theta(nk) + \Theta(n\log\frac{n}{k}) &= \Theta(nk + n\log\frac{n}{k}) \\ &= \Theta(n\log n + nk - n\log k) \\ &= \Theta(n\log n + n(k - \log k)) \\ \end{align} Θ(nk)+Θ(nlogkn)=Θ(nk+nlogkn)=Θ(nlogn+nk−nlogk)=Θ(nlogn+n(k−logk))

可以看到,修改过的算法的运行时间最低也是 Θ ( n log ⁡ n ) \Theta(n\log n) Θ(nlogn),与归并排序一样。如果 k k k 取的不好,比如 k > log ⁡ n k > \log n k>logn,修改过的算法的运行时间还会大于归并排序的 Θ ( n log ⁡ n ) \Theta(n\log n) Θ(nlogn)。

实践中如何选择 k

根据具体的计算环境,选择使得插入排序比归并排序快的最大的 k k k,但最大不要大于 log ⁡ n \log n logn。

相关推荐
GIS小天6 分钟前
AI+预测3D新模型百十个定位预测+胆码预测+去和尾2025年8月25日第170弹
人工智能·算法·机器学习·彩票
PAK向日葵1 小时前
【算法导论】XM 0823 笔试题解
算法·面试
岁月栖迟1 小时前
leetcode 49. 字母异位词分组
windows·算法·leetcode
Asmalin1 小时前
【代码随想录day 21】 力扣 77. 组合
算法·leetcode·职场和发展
2501_924878596 小时前
强光干扰下漏检率↓78%!陌讯动态决策算法在智慧交通违停检测的实战优化
大数据·深度学习·算法·目标检测·视觉检测
耳总是一颗苹果7 小时前
排序---插入排序
数据结构·算法·排序算法
YLCHUP7 小时前
【联通分量】题解:P13823 「Diligent-OI R2 C」所谓伊人_连通分量_最短路_01bfs_图论_C++算法竞赛
c语言·数据结构·c++·算法·图论·广度优先·图搜索算法
花火|8 小时前
算法训练营day62 图论⑪ Floyd 算法精讲、A star算法、最短路算法总结篇
算法·图论
GuGu20248 小时前
新手刷题对内存结构与形象理解的冲突困惑
算法
汤永红8 小时前
week4-[二维数组]平面上的点
c++·算法·平面·信睡奥赛