本文总结自《数据结构与算法分析(C++语言描述)》第四版第7章外部排序的内容。

一、基础部分

1. 为什么要区分外部排序与内部排序

所谓外部,是指磁盘、磁带、光盘等外部存储介质;那么内部相应指的是内存。
显然,他们之间的重要区别就是速度和容量,外存慢容量超大,内存超快容量小;
因此,当需要排序的数据量超过内存所能容纳的大小时,普通的排序算法比如快速排序,便无用武之地。本质的原因就是内存可以常数时间访问一个元素,但是外存比如硬盘,会有转动磁盘和移动磁头等不容忽视的时间开销。

2. 外部排序的维基解释

外排序(External sorting)是指能够处理极大量数据的排序算法。通常来说,外排序处理的数据不能一次装入内存,只能放在读写较慢的外存储器(通常是硬盘)上。外排序通常采用的是一种_“排序-归并”_的策略。在排序阶段,先读入能放在内存中的数据量,将其排序输出到一个临时文件,依此进行,将待排序数据组织为多个有序的临时文件。尔后在归并阶段将这些临时文件组合为一个大的有序文件,也即排序结果。

3. 简单排序-归并策略

3.1 概念先知

  1. 顺串:一组排过序的记录,称之为顺串,顺串长度在每趟外部排序过程中是不固定的;谨记此定义,否则阅读多相合并的内容会比较困难
  2. 排序:普通的内部排序算法,比如快速排序;
  3. 归并:指的是将两个已经排序的序列合并成一个序列的操作,即归并操作;

3.2 以磁带的 2 路合合并外排为例

3.2.1 假设
内存大小受限,因此假设它的大小只能容纳 M=3 个记录;
有4盘磁带,分别为 Ta1, Ta2, Tb1, Tb2;
待排数据预先存储在 Ta1;
3.2.2 外部排序过程详解

(1)数据原始状态

(2)每次从 Ta1 读取 M 个记录到内存中,排序完成,分别按顺串输出到 Tbn;得到如下结果,总共 5 个顺串, Tb1 三个, Tb2 两个;

(3)依次从 Tb1 和 Tb2 读取一个顺串进行合并,并输出到 Ta*,得到如下结果,总共三个顺串,Ta1 两个,Ta2 一个;

(4)重复(3)的做法,即第二趟合并,得到如下结果,两个顺串,Tb1 和 Tb2 各一个;

(5)继续第三趟合并,得到最终结果,如下,


二、高阶部分

1. 多路合并与多相合并

多路合并的作用在于减少外部排序所需的趟数,从 ⌈log(N/M)⌉ 降至 ⌈log k(N/M)⌉ (即以 k 为底,N/M 为真数),k>=3,N 指总记录数;多相合并则解决多路合并中对磁盘需求量大的问题,从 2k 数量的磁带降至 k+1。

2. 多路合并

多路合并与 2 路合并的方式基本相似,相信大家注意到了,两者唯一的区别是在合并上,2 路合并只需比较两个数从而可以得到最小值,但是多路合并有 k 个数,即需从 k 个数取出最小值,因此采取的合理方式是用**最小堆**来实现,这样每次通过对最小堆执行 deleteMin 操作,来逐一获取最小值。

2.1 3路合并过程详解

(1)数据初始状态

(2)依次从 Ta1 中读取 M 个记录,排序后按顺串依次输出到 Tbn,得到如下结果,Tb1 两个顺串,Tb2两个顺串,Tb3 一个顺串;

(3)第一趟合并结果,此时 3 个输出磁带未用完,只有两个顺串,Ta1 一个顺串, Ta2 一个顺串, 如下;

(4)第二趟合并,即最终外部排序结果,如下;

3. 多相合并

现在讨论如何将多路排序的 2k 盘磁带转换为 k+1 盘;这里以 2 路合并为例,通过 3 盘磁带实现。本节关心每趟合并中顺串的数量,而不关心具体的记录

3.1 假设

3 盘磁带分别为,T1,T2,T3,
输入数据在 T1 上,它将输出共 34 个顺串,
以两种方式对 T2 和 T3 分配顺串数量:(1)17 和 17;(2) 21 和 13;

3.2 分析

节省磁盘需要的牺牲就是增加合并总的趟数,多相合并中总趟数会因初始顺串数量分配方式不同而产生较大差异,这里初始顺串分配方式指将原始记录在内存排序完成后输出到空磁带上的过程。下面是图解,注意,每一趟顺串的记录数量不一样,
(1)17 和 17 的方式,总共 12 趟,拆开的原因在于,把结果合并到一个磁带上了,此时无法做合并操作,只能先拆分再合并。

(2)21 和 13 的方式,总共 8 趟,

3.3 总结

大家有兴趣可以自己在纸上画出初始分配方式为 22 和 12 的过程图,从上面图解过程基本可以知道,初始的顺串数量分配方式对最终外部排序需要的趟数有较大的影响。
但是有一种最优的分配方式,那就是斐波拉契数列,2 路合并就分配为 Fn-1 和 Fn-2, 如果无法分成两个斐波拉契数,则通过补充虚顺串(长度为0的顺串)来实现。拓展到 k 路合并,则需要 k 阶斐波那契数列来分配顺串。
k 阶斐波那契数列:

其初始条件:

三、讨论

  1. 从上面的总结分析可以看出,外部排序比内部排序对设备的依赖性更强。比如性能,以及数据读取方式(e.g. 硬盘和磁带)等。
  2. 高阶部分还有替换选择。

外部排序剖析-以磁带为例相关推荐

  1. 数据结构 | 【排序】外部排序

    零.核心部分 1. 实现外部排序的两个过程: 将整个初始文件分为多个初始归并段; 将初始归并段进行归并,直至得到一个有序的完整文件: 2. 时间组成: 内部排序所需要的时间 外存信息读写所需要的时间  ...

  2. mysql外部排序_深入浅出MySQL优先队列(你一定会踩到的order by limit 问题)

    0.先抛问题 假设字段category无索引且有重复值,order by category 和 limit 组合使用的结果会和预期不符. 问题复现: 表结构(就是两个字段) CREATE TABLE  ...

  3. 数据结构之外部排序:最佳归并树

    外部排序:最佳归并树 思维导图: 归并树的定义: 例: 最佳归并树(本质是一颗哈夫曼树): 所有的初始归并段一定能构造出一颗完美的哈夫曼树吗? 怎么选择补充虚短的个数? 思维导图: 归并树的定义: 例 ...

  4. 数据结构之外部排序:归并排序法

    外部排序:归并排序法 思维导图: 外部归并排序的原理: 外部归并排序的性能: 归并排序法的优化: 思维导图: 外部归并排序的原理: 第一步: 第二步: 问题:内存缓存区大小固定,外存数据元素分块后仍然 ...

  5. 数据结构(八):排序 | 插入排序 | 希尔排序 | 冒泡排序 | 快速排序 | 简单选择排序 | 堆排序 | 归并排序 | 基数排序 | 外部排序 | 败者树 | 置换-选择排序 | 最佳归并树

    文章目录 第八章 排序 一.排序的基本概念 (一)什么是排序 (二)排序的应用 (三)排序算法的评价指标 (四)排序算法的分类 (五)总结 二.插入排序 (一)算法思想 (二)算法实现 (三)算法效率 ...

  6. 八大内部排序+外部排序

    文章目录 排序划分 内部排序 1.直接插入排序 基本思想 算法描述 算法实现 2.希尔排序(递减增量排序) 基本思想 算法描述 3.简单选择排序 基本思想 算法描述 4.堆排序 基本思想 算法描述 5 ...

  7. 九大排序算法告诉你什么是内部排序和外部排序

    概述 排序有内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存. 我们通常所说的排序算法往往指的是内部排序算法, ...

  8. 内部排序和外部排序小结

    一.内部排序的比较: 1.从时间复杂度来看: 简单选择排序.直接插入排序和冒泡排序的平均复杂度都为 O(n2),并且实现过程也较为简单,但是直接插入排序和冒泡排序在最好的情况下时间复杂度可以达到 O( ...

  9. 外部排序归并排序 败者树

    一.定义问题 外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的.外部排序最常用的算法是多路 ...

最新文章

  1. Android--应用开发3(Android layout XML属性)
  2. 如何用css实现等高布局。
  3. SpringBoot非官方教程 | 第一篇:构建第一个SpringBoot工程
  4. PHP密码生成管理源码,php密码生成类(附源码)
  5. OpenGL RGTC Compressor压缩实例
  6. 牛客练习赛43 Tachibana Kanade Loves Probability(快速幂)
  7. Oracle备份还原
  8. vue 实现文本的拖拽_Vue-实现简单拖拽(自定义属性)
  9. linux脚本基础详解
  10. 基于JAVA幼儿园管理系统计算机毕业设计源码+系统+lw文档+部署
  11. Emacs基础使用教程及常见命令整理
  12. windows上未关闭135、445等危险端口引发的威胁
  13. OpenCV剪切图片圆形区域
  14. 原生JavaScript实现五子棋(直接上代码干货点赞收藏拿走)
  15. JAVA字符串中字符类型的识别和分类(汉字、数字、字母、特殊符号等)
  16. Python数据科学学习笔记之——机器学习专题
  17. 腾讯云一元服务器搭建个人网站详细教程
  18. Turf.js——用于地理空间分析的js库,处理各种地图算法
  19. Three.js + AI:WebGL的探险之旅
  20. 【教学类-06-03】20220327 X以内数字分合题(分)及生成word 打印docx纸(方法一)(Python VS )

热门文章

  1. Github如何添加合适的开源License(Apache License 2.0、MIT License、GPL3)
  2. Ubuntu 20.04 设置窗口打不开或者不显示解决方法
  3. 计算机箱图和结构,机箱设计结构篇 内部结构
  4. 什么是echo服务?如何开启?
  5. SQL_存储过程——获得一棵树的所有叶子节点
  6. YUV和libyuv相关了解
  7. web.Config配置文件的详细解释
  8. 激动人心,2022开放原子全球开源峰会报名火热开启
  9. 「WAVE SUMMIT 2022深度学习开发者峰会」火热来袭
  10. 如何用VI编辑器编辑二进制文件