数据结构—排序IV

一、            多路归并与败者树

 

【引】 归并趟数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叉树。




 





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值