首页/新闻资讯/正文详情

插入排序与希尔排序:原理、优化与实现

发布时间:2026/11/9 14:19:35 来源:云帆数科 栏目:资讯中心
插入排序与希尔排序:原理、优化与实现
1. 排序算法基础与插入排序原理排序算法是计算机科学中最基础也最重要的算法之一它直接影响着数据处理效率和系统性能。在实际开发中我们经常需要对数据进行排序操作比如电商网站的商品价格排序、社交媒体的时间线排序等。理解排序算法的原理和实现是每个程序员必备的基本功。插入排序Insertion Sort是最直观的排序算法之一它的工作原理类似于我们整理扑克牌的方式。想象一下当你拿到一手乱序的扑克牌时你会一张一张地将牌插入到已经排好序的牌堆中的适当位置。插入排序正是采用了这种思想。1.1 插入排序的基本实现让我们先来看一个简单的插入排序实现以Java为例public class InsertionSort { public static void sort(int[] arr) { for (int i 1; i arr.length; i) { int key arr[i]; int j i - 1; // 将arr[i]插入到已排序序列arr[0...i-1]中的正确位置 while (j 0 arr[j] key) { arr[j 1] arr[j]; j--; } arr[j 1] key; } } }这个实现展示了插入排序的核心逻辑外层循环遍历数组中的每个元素从第二个元素开始内层循环则将当前元素与已排序部分的元素进行比较找到合适的插入位置。1.2 插入排序的时间复杂度分析插入排序的时间复杂度取决于输入数据的初始顺序最佳情况当输入数组已经是有序的插入排序只需要进行n-1次比较时间复杂度为O(n)。最坏情况当输入数组是逆序的每次插入都需要比较和移动所有已排序元素时间复杂度为O(n²)。平均情况时间复杂度也是O(n²)。虽然插入排序在最坏情况下性能不佳但它有几个独特的优势对于小规模数据集插入排序通常比其他O(nlogn)的算法更快因为它的常数因子较小。当输入数据几乎有序时插入排序的效率非常高。它是稳定的排序算法即相等的元素排序后相对位置不变。它是原地排序算法只需要O(1)的额外空间。提示在实际应用中当待排序数组规模较小时通常n20许多高级排序算法如快速排序、归并排序会退化为使用插入排序因为在小规模数据上插入排序的实际运行时间更优。2. 插入排序的优化与变种虽然基本插入排序实现简单但我们仍然可以通过一些优化来提升它的性能特别是在特定场景下。2.1 二分查找优化在基本插入排序中我们使用线性搜索来找到插入位置。对于较大的数据集可以使用二分查找来减少比较次数public class BinaryInsertionSort { public static void sort(int[] arr) { for (int i 1; i arr.length; i) { int key arr[i]; int pos binarySearch(arr, 0, i - 1, key); // 移动元素 System.arraycopy(arr, pos, arr, pos 1, i - pos); arr[pos] key; } } private static int binarySearch(int[] arr, int low, int high, int key) { while (low high) { int mid low (high - low) / 2; if (arr[mid] key) { low mid 1; } else { high mid - 1; } } return low; } }这种优化将比较次数从O(n²)降低到O(nlogn)但移动元素的次数仍然是O(n²)因此整体时间复杂度仍然是O(n²)。不过在实际应用中当比较操作代价较高时比如比较的是复杂对象这种优化能带来明显的性能提升。2.2 哨兵技巧我们可以通过设置哨兵来减少内层循环的边界检查public class SentinelInsertionSort { public static void sort(int[] arr) { // 先找到最小值并放到首位作为哨兵 int minIndex 0; for (int i 1; i arr.length; i) { if (arr[i] arr[minIndex]) { minIndex i; } } swap(arr, 0, minIndex); // 现在arr[0]是最小值可以作为哨兵 for (int i 2; i arr.length; i) { int key arr[i]; int j i; while (arr[j - 1] key) { arr[j] arr[j - 1]; j--; } arr[j] key; } } private static void swap(int[] arr, int i, int j) { int temp arr[i]; arr[i] arr[j]; arr[j] temp; } }哨兵技巧消除了内层循环中的j0检查虽然时间复杂度没有改变但在实际运行中可以减少约一半的比较操作。3. 希尔排序插入排序的进化希尔排序Shell Sort是Donald Shell在1959年提出的一种改进的插入排序算法。它通过将原始列表分割成若干子序列来进行插入排序随着算法的进行子序列的长度逐渐增大最终整个列表作为一个序列进行排序。3.1 希尔排序的基本思想希尔排序的关键在于它使用了一个称为增量序列的概念。增量序列决定了如何将数组分割为子序列。最常用的增量序列是希尔原始提出的序列初始增量为n/2然后每次将增量减半直到增量为1。希尔排序的工作过程可以分为以下几个步骤选择一个增量序列t₁, t₂, ..., tₖ其中t₁ t₂ ... tₖ 1按增量序列个数k对序列进行k趟排序每趟排序根据对应的增量tᵢ将待排序列分割成若干长度为m的子序列分别对各子序列进行直接插入排序当增量因子为1时整个序列作为一个表来处理排序完成3.2 希尔排序的Java实现以下是希尔排序的一个基本实现使用希尔增量序列public class ShellSort { public static void sort(int[] arr) { int n arr.length; // 初始增量gap为n/2逐步缩小gap直到1 for (int gap n / 2; gap 0; gap / 2) { // 对每个子序列进行插入排序 for (int i gap; i n; i) { int temp arr[i]; int j; for (j i; j gap arr[j - gap] temp; j - gap) { arr[j] arr[j - gap]; } arr[j] temp; } } } }在这个实现中我们使用了移动法而非交换法来进行插入操作这通常比交换法更高效因为减少了不必要的赋值操作。3.3 希尔排序的性能分析希尔排序的时间复杂度分析相当复杂因为它依赖于所选择的增量序列。对于希尔原始提出的增量序列n/2, n/4, ..., 1最坏情况下时间复杂度仍然是O(n²)。然而通过选择更好的增量序列可以显著提高希尔排序的性能Hibbard增量序列1, 3, 7, 15, ..., 2ᵏ-1最坏时间复杂度为O(n^(3/2))Sedgewick增量序列1, 5, 19, 41, 109, ...最坏时间复杂度为O(n^(4/3))在实际应用中希尔排序的性能通常介于O(nlogn)和O(n²)之间对于中等大小的数据集非常有效。它不需要额外的内存空间原地排序并且代码实现相对简单。注意希尔排序是不稳定的排序算法因为在不同的增量排序过程中相等的元素可能会改变相对位置。4. 希尔排序的增量序列选择增量序列的选择对希尔排序的性能有着决定性影响。让我们深入探讨几种常见的增量序列及其特点。4.1 常见的增量序列希尔原始序列Shells original sequence公式n/2, n/4, ..., 1最坏时间复杂度O(n²)优点简单易实现缺点效率不高尤其是对大规模数据Hibbard序列公式1, 3, 7, 15, ..., 2ᵏ-1最坏时间复杂度O(n^(3/2))优点比希尔序列有明显改进缺点增量之间差距较大Sedgewick序列公式1, 5, 19, 41, 109, ...交替使用9×4ⁱ-9×2ⁱ1和4ⁱ-3×2ⁱ1最坏时间复杂度O(n^(4/3))优点目前已知最好的增量序列之一缺点计算稍复杂Knuth序列公式1, 4, 13, 40, ..., (3ᵏ-1)/2最坏时间复杂度O(n^(3/2))优点实现简单性能较好缺点不如Sedgewick序列高效4.2 增量序列的Java实现示例以下是使用Sedgewick增量序列的希尔排序实现public class SedgewickShellSort { public static void sort(int[] arr) { int n arr.length; // 生成Sedgewick增量序列 int[] sedgewick getSedgewickSequence(n); // 从最大的增量开始 for (int k sedgewick.length - 1; k 0; k--) { int gap sedgewick[k]; for (int i gap; i n; i) { int temp arr[i]; int j; for (j i; j gap arr[j - gap] temp; j - gap) { arr[j] arr[j - gap]; } arr[j] temp; } } } private static int[] getSedgewickSequence(int n) { ListInteger sequence new ArrayList(); int k 0; while (true) { int term; if (k % 2 0) { term (int) (9 * (Math.pow(4, k) - Math.pow(2, k)) 1); } else { term (int) (Math.pow(4, k 2) - 3 * Math.pow(2, k 2) 1); } if (term n) break; sequence.add(term); k; } return sequence.stream().mapToInt(i - i).toArray(); } }在实际应用中Sedgewick序列通常能提供最佳性能特别是对于大规模数据集。不过它的计算稍复杂因此在某些情况下简单的Knuth序列可能是更好的折中选择。4.3 增量序列选择建议选择增量序列时需要考虑以下因素数据规模对于小规模数据简单的希尔序列可能就足够了大规模数据则需要更高效的序列。数据特性如果数据已经部分有序某些增量序列可能表现更好。实现复杂度更复杂的序列可能需要更多的预处理时间。稳定性要求如果需要稳定排序希尔排序可能不是最佳选择。根据我的经验在大多数通用场景下Knuth序列提供了良好的平衡点实现简单性能优于原始希尔序列又不像Sedgewick序列那样复杂。只有在性能极其关键且数据规模非常大的情况下才值得使用Sedgewick序列。

相关推荐

AI Agent时代的能力原子:Skills的本质与工程实践
AI Agent时代的能力原子:Skills的本质与工程实践

1. “skills”不是功能菜单,而是AI Agent时代的底层能力基建最近两周,我在三个不同技术团队的内部分享会上,都被问到同一个问题:“你们说的skills到底指什么?是Claude插件?还是VS Code里的扩展?… · 2026/11/3 13:47:09

技能体系化:把零散技能变成可调用的能力资产
技能体系化:把零散技能变成可调用的能力资产

有一段时间我特别困惑:明明手机里存着几十个技能教程,收藏夹里躺着上百篇干货,可一到真正要做事情的时候,脑子里能调用的东西屈指可数。后来我才意识到,问题不在"学得少",而在"没体系"… · 2026/11/3 18:46:13

纯前端零依赖秒级计时页面:时间戳计时与英文签名轮换实现
纯前端零依赖秒级计时页面:时间戳计时与英文签名轮换实现

不少做前端的朋友都碰到过这种需求:手里有一份静态页面,想在上面挂一个能自动走秒的时钟,顺便再配一句有点格调的英文签名,做成一个能直接双击打开、不依赖任何后端的小工具页。这次要聊的就是这么一个东西——qq_seconds.html配合… · 2026/11/3 21:51:55

高压电工证社保福利多久拿证才能上岗找工作
高压电工证社保福利多久拿证才能上岗找工作

高压电工证社保福利多久拿证才能上岗找工作 现在找工作,特种作业证是基本门槛,尤其是高压电工证,很多单位招人时第一条件就是看你有没有这证。很多人问: 高压电工证社保福利 怎么样? 多久拿证… · 2026/11/9 14:18:58

潍坊低压电工证包通过保姆级教程:实操考试心里没底怕挂科怎么办
潍坊低压电工证包通过保姆级教程:实操考试心里没底怕挂科怎么办

潍坊低压电工证包通过保姆级教程:实操考试心里没底怕挂科怎么办 实操考试心里没底怕挂科,这几乎是所有准备报考低压电工证的朋友的共同心声。特别是对来自开封水利工程领域的从业者来说,低压电工证不仅是上岗的门槛,更是未来职业发展的关键一步。很多人担… · 2026/11/9 14:18:58

高压电工证社保福利你知道吗?考前押题帮你搞定学历不高怕报不上名的难题
高压电工证社保福利你知道吗?考前押题帮你搞定学历不高怕报不上名的难题

高压电工证社保福利你知道吗?考前押题帮你搞定学历不高怕报不上名的难题 你是不是也这样,学历不高,担心自己连高压电工证都报不了名?别急,今天就来聊聊高压电工证社保福利,还有考前押题怎么用,帮你少走弯路。 案例背景:一个平顶山市政电工的日常… · 2026/11/9 14:18:58

嘉兴怎么考电工证报名入口与办理流程多少钱
嘉兴怎么考电工证报名入口与办理流程多少钱

嘉兴怎么考电工证报名入口与办理流程多少钱 不知道去哪报名怕被中介坑?嘉兴怎么考电工证,现在很多人想了解电工证的具体报名流程和费用,但信息混杂,真假难辨,让人摸不着头脑。别担心,这篇文章手把手教你如何避开坑,顺利拿到电工证,而且费用一清二楚,… · 2026/11/9 14:18:58

工地太忙根本没时间复习考试?6月1号电工证改革在哪考最靠谱
工地太忙根本没时间复习考试?6月1号电工证改革在哪考最靠谱

工地太忙根本没时间复习考试?6月1号电工证改革在哪考最靠谱 工地太忙根本没时间复习考试,这几乎是每个特种作业人员的心声。特别是6月1号电工证改革之后,很多人的证书要重新考,但白天忙得脚不沾地,晚上还得照顾家庭,复习考试成了奢望。 在哪考… · 2026/11/9 14:18:58

新手考电工证必备知识在哪考才靠谱
新手考电工证必备知识在哪考才靠谱

新手考电工证必备知识在哪考才靠谱 实操考试心里没底怕挂科?你不是一个人。很多刚接触电工证的新手,最怕的就是动手操作时手忙脚乱,一不小心就挂科,白白浪费时间精力。而且,很多人不知道【在哪考】这个问题,其实也是导致他们焦虑的重要原因。今天就从南… · 2026/11/9 14:17:58

电工证丢失还能补吗?千万别踩坑,丢了证等于失业
电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/9 2:05:04

电力电缆作业证直播报名入口与办理流程良心建议
电力电缆作业证直播报名入口与办理流程良心建议

电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/9 3:11:26

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/9 5:24:17

电工证不需要考复审延期怎么办理 通过率揭秘
电工证不需要考复审延期怎么办理 通过率揭秘

电工证不需要考复审延期怎么办理 通过率揭秘 不知道去哪报名怕被中介坑?电工证不需要考复审延期怎么办理?最近不少学员都在问这个问题,尤其是刚拿到证的新手,对复审流程一知半解,生怕被培训机构套路。别担心,今天咱们就来聊聊电工证复审的真相,尤其是… · 2026/11/9 0:00:54

砀山哪里考电工证的多 电工证报考别踩坑 郑州报考避坑指南
砀山哪里考电工证的多 电工证报考别踩坑 郑州报考避坑指南

砀山哪里考电工证的多 电工证报考别踩坑 郑州报考避坑指南 工地太忙根本没时间复习考试,这几乎是所有一线施工人员的共同心声。尤其是像电工这样的特种作业,操作证不仅关系到能不能上工,还直接关系到工资高低和职业发展。可偏偏,很多人连怎么报名、去哪… · 2026/11/9 0:00:54

南方电网电工作业含金量高吗?应届生怎么考怎么干?
南方电网电工作业含金量高吗?应届生怎么考怎么干?

南方电网电工作业含金量高吗?应届生怎么考怎么干? 工地太忙根本没时间复习考试,这不是个别现象,而是很多刚毕业的工程类学生面临的现实。南方电网电工作业的证书,听起来门槛不低,但 含金量… · 2026/11/9 0:00:54

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/9 11:23:35

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/9 11:23:58

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/9 11:25:08

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码