外部排序算法总结

一.内排总结

在之前博客里,博主已经介绍了各种内部排序算法的原理和C语言代码实现,不懂的朋友可以在同系列专栏里选择查看,今天介绍常见排序算法的最后一点,也就是外部排序。在此之前,我们先对外部排序的各种算法做一下简单的总结。

算法种类时间复杂度(最好)时间复杂度(最坏)时间复杂度(平均)空间复杂度稳定性
折半插入排序O(n)O(n2 )O(n2 )O(1)
直接插入排序O(n)O(n2 )O(n2 )O(1)
希尔排序------------O(1)
冒泡排序O(n)O(n2 )O(n2 )O(1)
快速排序O(nlog2 n)O(n2 )O(nlog2 n)O(log2 n)
简单选择排序O(n2 )O(n2 )O(n2 )O(1)
堆排序O(nlog2 n)O(nlog2 n)O(nlog2 n)O(1)
2路归并排序O(nlog2 n)O(nlog2 n)O(nlog2 n)O(n)
基数排序O(d(n+r))O(d(n+r))O(d(n+r))

针对每种排序算法的效率差别,我已经总结在上面的表格里了,同时我后面还写了一份针对408范围内的所有数据结果和算法的效率分析专项总结,大家可以期待一首。

二.外部排序

1.外排概念

前面介绍过的排序方法都是在内存中进行的(称为内部排序)。而在许多应用中,经常需要对大文件进行排序,因为文件中的记录很多,无法将整个文件复制进内存中进行排序。因此,需要将待排序的记录存储在外存上,排序时再把数据一部分一部分地调入内存进行排序,在排序过程中需要多次进行内存和外存之间的交换。这种排序方法就称为外部排序

2.排序方法

文件通常是按块存储在磁盘上的,操作系统也是按块对磁盘上的信息进行读写的。因为磁盘读/写的机械动作所需的时间远远超过内存运算的时间(相比而言可以忽略不计),因此在外部排序过程中的时间代价主要考虑访问磁盘的次数,即I/O次数。

外部排序通常采用归并排序法。它包括两个阶段:①根据内存缓冲区大小,将外存上的文件分成若干长度为l的子文件,依次读入内存并利用内部排序方法对它们进行排序,并将排序后得到的有序子文件重新写回外存,称这些有序子文件为归并段或顺串;②对这些归并段进行逐趟归并,使归并段(有序子文件)逐渐由小到大,直至得到整个有序文件为止。

3.举例说明

在这里插入图片描述

用上面这个例子来说明,我们假设左边是外存中的待排序序列,右边是我们的内存。(这里我们只是举例,实际上用到外部排序时,外存数据量非常庞大,这里只是演示。)这里涉及一部分操作系统的知识点,但都是计算机专业,应该都学过,内存的数据修改完之后是要写回外存的,所以我们这里有两个输入缓冲区和一个输出缓冲区,输入缓冲区用来读入磁盘数据,输出缓冲区用于把数据写回磁盘。

由于我们的外部排序是基于归并排序算法的,归并排序算法要求初始序列有序,所以这里我们在开始外部排序之前(或者说正式排序之前也就是叫预排序),我们需要构造初始有序序列。我们首先从磁盘读取两个块数据进入内存,然后在内存中对这两个块的数据进行某一种内部排序。

在这里插入图片描述

针对本例的前两个数据块,当排序结果写满一个输出缓冲区时,我们把输出缓冲区的数据写回外存。以此类推,预排序就是把外存的数据每两个块读入内存后排序,排序后写回结果。这里的几个块一读是基于内存中输入缓冲区的个数有关,它的选取和外部以及内部空间的大小有关。

预排序后的结果应该是这样的:

在这里插入图片描述

接下来我们的外存中就存在初始有序序列了,所以可以开始进行正常的归并排序了。这里注意,预排序是两个数据块一读,所以两个数据块就形成了一个初始子序列哦,这里只有8个初始子序列哦。接下来把子序列1和子序列2的第一块分别读入输入缓冲区,开始内部排序,还是一样,输出缓冲区已满我们就写回外存。这里还有一点注意哦,当某个时刻比如输入缓冲区1的数据完了,我们不是把输入缓冲区2的数据直接填到输出缓冲区,而是把原来子序列后面的数据块读入内存哦(假设我们这里使用的内部排序算法也是归并排序),这样两个子序列是不是又合并成了一个大的子序列。然后两个大的子序列又可以合并成一个更大的序列,直到最后只有一个序列表示我们外部排序完成。

4.效率分析

我们应该知道,这里影响时间效率的最大因素其实是I/O口的读取次数,内部排序的时间相较于I/O口的读取的读取时间是很少的。所以如果我们想要提高外部排序的时间效率,那么就得想办法减少I/O口的读取次数。

一般地, 对r个初始归并段,做k路平衡归并,归并树可用严格k叉树(即只有度为k与度为0的结点的k叉树)来表示。第一趟可将r个初始归并段归并为 ⌈ r / k ⌉ \lceil{r/k}\rceil r/k 个归并段,以后每趟归并将m个归并段归并成 ⌈ m / k ⌉ \lceil{m/k}\rceil m/k个归并段,直至最后形成一个大的归并段为止。树的高度-1 =「logr1=归并趟数S。可见,只要增大归并路数k,或减少初始归并段
个数r,都能减少归并趟数s,进而减少读写磁盘的次数,达到提高外部排序速度的目的。

三.败者树

上节讨论过,增加归并路数k能减少归并趟数s,进而减少I/O次数。然而,增加归并路数k时,内部归并的时间将增加。做内部归并时,在k个元素中选择关键字最小的记录需要比较k-1次。每趟归并n个元素需要做(n-1)(k-1)次比较,s趟归并总共需要的比较次数随k增长而增长。因此内部归并时间亦随k的增长而增长。这将抵消由于增大k而减少外存访问次数所得到的效益。因此,不能使用普通的内部归并排序算法。为了使内部归并不受k的增大的影响,引入了败者树。 败者树是树形选择排序的一种变体,可视为一棵完全二叉树。k个叶结点分别存放k个归并段在归并过程中当前参加比较的记录,内部结点用来记忆左右子树中的“失败者”,而让胜者往上继续进行比较,一直到根结点。若比较两个数,大的为失败者、小的为胜利者,则根结点指向的数为最小数。
在这里插入图片描述

这是实现一个5路归并的败者树的例子。

可见,使用败者树后,内部归并的比较次数与k无关了。因此,只要内存空间允许,增大归并路数k将有效地减少归并树的高度,从而减少I/O次数,提高外部排序的速度。值得说明的是,归并路数k并不是越大越好。归并路数k增大时,相应地需要增加输入缓冲区的个数。若可供使用的内存空间不变,势必要减少每个输入缓冲区的容量,使得内存、外存交换数据的次数增大。当k值过大时,虽然归并趟数会减少,但读写外存的次数仍会增加。

四.置换-选择排序(生成初始序列)

减少初始归并段个数r也可以减少归并趟数S。若总的记录个数为n,每个归并段的长度为l,则归并段的个数r=「nll 1。采用内部排序方法得到的各个初始归并段长度都相同(除最后一段外),它依赖于内部排序时可用内存工作区的大小。因此,必须探索新的方法,用来产生更长的初始归并段,这就是本节要介绍的置换-选择算法。

设初始待排文件为FI,初始归并段输出文件为FO,内存工作区为WA, FO和WA的初始状态为空,WA可容纳w个记录。置换选择算法的步骤如下:

  • 1)从FI输入w个记录到工作区WA。
  • 2)从WA中选出其中关键字取最小值的记录,记为MINIMAX记录。
  • 3)将MINIMAX记录输出到FO中去。
  • 4)若FI不空,则从FI输入下一个记录到WA中。
  • 5)从WA中所有关键字比MINIMAX记录的关键字大的记录中选出最小关键字记录,作为新的MINIMAX记录。
  • 6)重复3) ~5),直至在WA中选不出新的MINIMAX记录为止,由此得到一个初始归并段,输出一个归并段的结束标志到FO中去。
  • 7)重复2)~6),直至WA为空。由此得到全部初始归并段。

五.最佳归并树

文件经过置换-选择排序后,得到的是长度不等的初始归并段。下 面讨论如何组织长度不等的初始归并段的归并顺序,使得I/O次数最少?假设由置换选择得到9个初始归并段,其长度(记录数)依次为9, 30, 12, 18,3, 17,2,6,24。现做3路平衡归并,其归并树如图8.16所示。在图左中,各叶结点表示一个初始归并段,上面的权值表示该归并段的长度,叶结点到根,的路径长度表示其参加归并的趟数,各非叶结点代表归并成的新归并段,根结点表示最终生成的归并段。树的带权路径长度WPL为归并过程中的总读记录数,故I/O次数= 2xWPL = 484。

显然,归并方案不同,所得归并树亦不同,树的带权路径长度(I/O次数)亦不同。为了优化归并树的WPL,可以将哈夫曼树的思想推广到m叉树的情形,在归并树中,让记录数少的初始归并段最先归并,记录数多的初始归并段最晚归并,就可以建立总的I/O次数最少的最佳归并树。上述9个初始归并段可构造成一棵如图右所示的归并树,按此树进行归并,仅需对外存进行446次读/写,这棵归并树便称为最佳归并树。

在这里插入图片描述

六.总结

好了,到这里408范围内的数据结构和算法部分我们已经学完了,接下来转战计算机网络和操作系统部分。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/61356.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

高翔《自动驾驶中的SLAM技术》代码详解 — 第6章 2D SLAM

目录 6.2 扫描匹配算法 6.2.1 点到点的扫描匹配 6.2 扫描匹配算法 6.2.1 点到点的扫描匹配 // src/ch6/test_2dlidar_io.cc // Created by xiang on 2022/3/15. // #include <gflags/gflags.h> #include <glog/logging.h> #include <opencv2/highgui.hpp>…

Redis—全局命令

Redis—全局命令 &#x1f50e;get / set&#x1f50e;常用全局命令keysexistsdelexpirettlkey 的过期策略type Redis 官网 Redis 中的命令不区分大小写 进入 Redis 客户端 redis-cli -h Redis 服务器的 IP 地址 -p Redis 服务器的端口号省略 -h 表示 Redis 服务器的 IP 地址…

OKR管理策略:为开发团队注入动力

引言 在这个快速变化的世界中&#xff0c;公司需要迅速应对市场变化&#xff0c;并保持其目标和战略的清晰性和一致性。而OKR&#xff08;Objectives and Key Results&#xff09;正是这个挑战的解决方案之一。OKR的实施可以帮助开发团队明确目标&#xff0c;关注关键结果&…

powershell几句话设置环境变量

设置环境变量比较繁琐&#xff0c;现在用这段话&#xff0c;在powershell中就可以轻松完成。 $existingPath [Environment]::GetEnvironmentVariable("Path", "Machine") $newPath "C:\Your\Path\Here"if ($existingPath -split ";"…

DSP学习笔记

一个汇编语句包含4个固定顺序的区域&#xff1a;标号&#xff08;必须从第一列开始 不能空格&#xff0c;后面可以有&#xff1a;也可以没有&#xff09; 助记符 操作数 注释&#xff08;用分号或者星号来注释&#xff09;伪指令用.开头&#xff0c;注释可以用第一列开始写&…

软件设计师(五)软件工程基础知识

一、软件工程概述 软件开发和维护过程中所遇到的各种问题称为“软件危机”。 软件工程是指应用计算机科学、数学及管理科学等原理&#xff0c;以工程化的原则和方法来解决软件问题的工程&#xff0c;其目的是提高软件生产率、提高软件质量、降低软件成本。 #mermaid-svg-h3j6K…

大数据指标体系-笔记

指标体系 1 总体流程图 1.1 2 模型‘ 2.1 OSM OSM(Object,Strategy,Measure) 「业务度量」涉及到以下两个概念:一个是KPI ,用来直 接衡量策略的有效性;一个是Target,是预先给出的值,用来判断是否达到预期 2.2 UJM User, Journey, Map 2.3 AARRR-海盗 AARRR(Acquisitio…

【C语言】通讯录3.0 (文件存储版)

前言 通讯录是一种记录联系人信息的工具&#xff0c;包括姓名、电话号码、电子邮件地址、住址等。 文章的一二三章均于上一篇相同&#xff0c;可以直接看第四章改造内容。 此通讯录是基于通讯录2.0&#xff08;动态增长版&#xff09;的基础上进行增加文件操作功能&#xff0c…

【多线程学习6】synchronized关键字

【多线程学习6】synchronized关键字 一、synchronized关键字是什么&#xff1f;有什么作用&#xff1f; synchronized关键字是Java线程同步的关键字&#xff0c;其可以修饰方法或代码块&#xff0c;并可以保证其修饰的方法或代码块在任意时刻只能有一个线程执行。 synchroni…

K8s集群安全机制

1.访问K8s集群的时候&#xff0c;需要经过三个步骤完成具体操作 &#xff08;1&#xff09;认证&#xff08;2&#xff09;鉴权&#xff08;授权&#xff09;&#xff08;3&#xff09;准入控制 进行访问的时候&#xff0c;过程中都要经过apiserver&#xff0c;apiserver做统…

java,python,c++有什么区别,python java c c++区别

大家好&#xff0c;给大家分享一下java,python,c有什么区别&#xff0c;很多人还不知道这一点。下面详细解释一下。现在让我们来看看&#xff01; 从这四种语言的难度、受欢迎度还有作用以及优点缺点给楼主做一个全面的分析&#xff0c;我们可以从中了解其区别&#xff0c;以及…

AP2400 LED汽车摩灯照明电源驱动 过EMC DC-DC降压恒流IC

产品特点 宽输入电压范围&#xff1a;5V&#xff5e;100V 可设定电流范围&#xff1a;10mA&#xff5e;6000mA 固定工作频率&#xff1a;150KHZ 内置抖频电路&#xff0c;降低对其他设备的 EMI干扰 平均电流模式采样&#xff0c;恒流精度更高 0-100%占空比控制&#xff0…

【状态估计】基于UKF法、AUKF法的电力系统三相状态估计研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

并查集练习—省份数量

上一篇中讲了并查集及其原理&#xff0c;在这篇文章中简单应用一下。如果对并查集不是很了解强烈建议先看上一篇。 题目&#xff1a; 有 n 个城市&#xff0c;其中一些彼此相连&#xff0c;另一些没有相连。如果城市 a 与城市 b 直接相连&#xff0c;且城市 b 与城市 c 直接相…

大数据Flink(五十七):Yarn集群环境(生产推荐)

文章目录 Yarn集群环境(生产推荐) 一、准备工作

目标检测中的IOU

IOU 什么是IOU?IOU应用场景写代码调试什么是IOU? 简单来说IOU就是用来度量目标检测中预测框与真实框的重叠程度。在图像分类中,有一个明确的指标准确率来衡量模型分类模型的好坏。其公式为: 这个公式显然不适合在在目标检测中使用。我们知道目标检测中都是用一个矩形框住…

【福建事业单位-推理判断】02图形推理(数量-空间重构)

【福建事业单位-推理判断】02图形推理&#xff08;数量-空间重构&#xff09; 一、数量规律1.1点&#xff08;交点、切点&#xff09;点的细化考法总结 1.2线条&#xff08;线条的数量&#xff09;线的细化考点一笔画&#xff08;重点&#xff09;一笔画的判定 总结 1.3 面面的…

flutter开发实战-video_player视频播放功能及视频缓存

flutter开发实战-video_player视频播放功能及视频缓存 最近开发过程中video_player播放视频&#xff0c; 一、引入video_player 在pubspec.yaml引入video_player video_player: ^2.7.0在iOS上&#xff0c;video_player使用的是AVPlayer进行播放。 在Android上&#xff0c;…

医疗实施-集成平台下门诊就诊流程详解

目录 集成平台下门诊就诊流程详解1.患者建档2. 门诊挂号3. 医生就诊4.处方开立5.费用收取、6、科室执行医嘱集成平台下门诊就诊流程详解 这篇文章是考虑医院使用了集成平台之后,门诊就诊流程详解。与我的文章《医疗实施-门诊就诊流程详解》的大致一样,供学有余力的人阅读。 …

AMASS database

AMASS是一个由不同的光学标记运动捕捉数据集统一表示在一个公共框架和参数化下的大型人体运动数据库。它包含了超过40小时的运动数据&#xff0c;涵盖了300多个主体和11000多个运动。它使用了SMPL人体模型&#xff0c;它是一种基于混合形状和姿态空间的生成式人体模型&#xff…