1. 外排序的基本过程
外排序的基本方法是归并排序法,它分为两个步骤:
- 生成若干个初始归并段(顺串):将一个文件(含待排序的数据)中的数据分段读入内存,在内存中对其进行内排序,并将经过排序的数据段(有序段)写到多个外存文件上。
- 多路归并:对这些初始归并段进行多遍归并,使得有序的归并段逐渐扩大,最后在外存上形成整个文件的单一归并段, 这也就完成了这个文件的外排序。
外排序的时间主要花费在内、外存数据交换(对应存取时间)和内排序上。
一般情况下,初始归并段的个数越多,多路归并的性能越差,可以将置换—选择排序算法用于生成长度较大的初始归并段,从而减少初始归并段的个数。
在多路(k
路)归并中可以采用平衡归并方法,其中频繁的操作是从k
个记录中选择关键字最少的记录。如果这种操作采用简单比较来实现,那么 k
越大,磁盘读/写的次数越少,但记录之间的比较次数相应增加,所以整个外排序的性能不一定 会提高。
如果这种操作采用败者树来实现,可以推出记录之间的比较次数与k
无关,所以只要内存空间允许,增大归并路数k
会有效地减少归并树的高度,从而减少读/写磁盘的次数,提高外排序的速度。
当所有初始归并段的记录个数不相同时,按照最佳归并树的方案进行归并可以使归并过程中对外存的读/写次数最少,从而提高归并性能。
有简单的题目:对于 100 个长度不等的初始归并段,在构建 5 路最佳归并树时需要增加多少个虚段?
- 这里
m = 100
,k = 5
,求出u = (m - 1) % (k - 1) = 3
,需要增加k - 1 - u = 1
个虚段。
2. 海量数据的外排序
海量数据的排序出了可以采用前面的基本外排序方法以外,还可以采用位图和 MapReduce
实现。在完成这类题目时需要估算内存空间的和数据存储空间的大小。
2.1 位图
位图就是将 int
或者 long
数据看成一位一位的,每一位对应一个地址,该地址表示数
据值。如果存在某个数据值,将该数据值作为地址,并将这个地址的位设置为 1,否则为 0。
采用位图方案需要考虑其特殊性:
- 排序的数据为整数,没有任何其他与之关联的数据
- 整数值限定在一个范围内
- 没有重复的整数
例如,求 40 亿个非负整数(int
) 中没有出现的整数、对 40 亿个非负整数(int
)进行递增排序等题目都可以采用位图实现。
2.2 MapReduce
MapReduce
是种编程模型, 用于大规模数据集 (大于1TB
)的并行运算。 它将大批量的数据分解执行,然后将结果合并成最终结果。实际上 MapReduce
的原理就是一个归并排序。
3. 常见题目解析
1. 以归并排序为例,说明内排序和外排序的不同,并指出外排序中如何提高操作效率。
- 内排序中的归并排序是在内存中进行的归并排序,所有数据都要调入内存,所需的辅助空间为 O ( n ) O(n) O(n)。外排序的归并排序是将外存中的多个有序子文件合并成一个有序子文件,所需的辅助空间仅与归并的路数相关。另外,外排序涉及大量的内、外存数据交换,而内排序中不需要内、外存数据交换。
- 外排序的效率主要取决于读/写外存的次数,当m个初始子文件采用
k
路平衡归并时,其归并趟数 s = ⌈ l o g k m ] s={\lceil} log_k m] s=⌈logkm],通常s
越大读/写外存的次数越多,当采用败者树实现归并时增大k
和减少m
都可以减少s
,从而提高外排序的效率。
2. 若要在N
个海量数据(超过 10 亿,不能一次全 部放入内存)中找出最大的 k
个元素(内存中可以容纳 k
个元素),最好采用什么数据结构和策略?请详细说明你采用的数据结构和策略,并用时间复杂度和空间复杂度来说明理由。
- 首先读入
k
个元素,假设第 1 次读取的k
个元素就是前k
个最大元素,把k
个元素建成小根堆。然后从第k+1
个元素开始,读取的每个元素d
都与堆顶的元素进行比较,如果元素d
大于堆顶元素,则把堆顶的元素替换成d
,再将其调整成小根堆(时间为 l o g 2 k log_2 k log2k)。当所有数据都读入并比较完之后,这个小根堆里面的所有元素就是最大的k
个元素。 - 该算法的时间复杂度为 O ( N l o g k ) O(Nlogk) O(Nlogk)、空间复杂度为 O ( k ) O(k) O(k)。
3. 有k
(k>10
)个有序文件,共存放 10 亿个整数,给出将其合并为一个有序文件的思路。
- 采用外排序的基本过程。首先从
k
个有序文件中各自读取第 1 个整数创建含k
叶结点的败者树,每个叶结点对应一个有序文件。 然后将冠军写入结果文件,再从冠军所在的文件中读取下一个整数填充到对应的叶结点中,调整败者树,将新产生的冠军写入结果文件,以此类推,直到所有文件的数据处理完毕。
关于败者树算法、败者树与堆的关系与区别、赢者树暂时就不在这个版块更新了,在此推荐几个Link,可以学习一下:
堆与败者树比较
堆,赢者树,败者树的区别与联系