赞
踩
一、 多路归并与败者树
【引】 归并趟数S=⌈ ⌉。然而当增加归并路数m是,内部归并时间将增加。做内部归并时,在m个元素中选择关键字最小的记录需要比较m-1次(由于每个归并段之前是有序的,即从m个归并段的第一个记录的相互比较中选出最小者需要m-1次比较)。每趟归并n-1个元素需要做(n-1)*(m-1)次比较,S趟归并总共的比较次数为:
S*(n-1)*(m-1)= ⌈ ⌉*(n-1)*(m-1)=⌈ ⌉*(n-1)*(m-1)/⌈ ⌉
其中,⌈ ⌉*(n-1)在初始归并段个数r与记录个数n一定时是常数,而(m-1)/ ⌈ ⌉
随m增长而增长(线性函数大于对数函数)。这将抵消由于增大m而减少外存访问次数所得到的效益,因此不能用普通的内部归并排序算法。
【败者树】
败者树是对树形选择排序的一种变形,可看做一颗完全二叉树。每个叶子节点存放归并段在归并过程中当前参加比较的记录,内部节点用来记忆左右子树中的“失败者“,而让胜者往上继续进行比较,一直到根节点。如果比较两个数,大的为失败者,小的为胜利者,则根结点指向的树为最小数。
所以总的比较次数:S*(n-1)*⌈ ⌉=⌈ ⌉*(n-1)*⌈ ⌉=(n-1)⌈ ⌉
其中r是初始归并段个数
【总结】
使用败者树后,内部归并的比较次数和m的无关了,可见只要内存空间允许,增大归并路数m将有效减少归并树的高度,从而减少I/O次数d,提高外部排序速度。 但并不是m越大越好,因为这会增大输入缓冲区的个数(m路对应m个输入缓冲区和1个输出缓冲区),如果可用内存不变,势必减少每个缓冲区的容量,使得内外存交换数据次数增大。
二 置换-选择排序(初始化归并段)
【引】 由S=⌈ ⌉可知,减少初始归并段的个数r也可以减少归并趟数S。
若总的记录个数为n,每个归并段长度为l,则初始归并段个数就是m=⌈ ⌉,可见只有归并段不等长时,才会减少归并段数。
设待排文件FI,初始化归并段文件FO(目标结果),内存工作区WA,内存工作空间可容纳w个记录。
【置换-选择算法】
1. 从待排文件F1输入w个记录到工作区WA中
2. 从内存工作区WA中选出其中关键字最小值的记录,记为MINIMAX(以后再选出关键字比它大的记录归入本归并段,比它小的归入下一归并段)
【注】
l 每次从工作区中选择的是比MINIMAX大的关键字记录中最小关键字记录
l 选择MINIMAX记录的过程需利用败者树
三、 最佳归并树
【引】文件经过置换-选择排序后,得到的是长度不等的初始归并段。
下面将讨论如何组织归并顺序,使IO访问次数最少。
该节总过是从三个方面:最小化初始化归并段,最优化归并顺序,最优化归并排序。
设置换-选择得到9个初始归并段,其长度(记录数)依次为:9,30,12,18,3,17,2,6,24
这里举得是严格的3叉树,要是遇到非严格的情况如何处理呢?
-à添加长度为0的虚段,依旧按照哈夫曼树的原则构造,可保证WPL最小
如上例中去掉了 30这个归并段,即9,12,18,3,17,2,6,24(8个)
8个归并段构成3叉树, =(8-1)%(3-1)=1,说明7((7-1)%(3-1)=0)个归并段刚好构成一个严格3叉树,(假设以5为根的树看做一个叶子),为此将叶子5变成一个内结点,再添加3-1-1=1个空归并段,就可以构造成一个严格m叉树。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。