数据结构-外部排序

目录

一、外部排序概念

二、归并排序

三、多路平衡归并与败者树

四、置换-选择排序(生成初始归并段)

五、最佳归并树


一、外部排序概念

    对大文件进行排序。而文件中记录很多,无法将整个文件复制到内存中进行排序,因此,需要将待排序的记录存储在外存上,排序时再把数据一部分一部分地调入内存进行排序,在排序过程中需要进行多次内存和外存之间的交换。

    文件通常是按块存储在磁盘上,操作系统也是按块对磁盘上的信息进行I/O。因为磁盘I/O的动作所需时间远大于内存中运算的时间,因此外部排序中的时间代价主要为I/O次数。

二、归并排序

步骤:1、根据内存缓冲区的大小,将外存上的文件分成若干长度为x的子文件,依次读入内存并利用内部排序算法进行排序,并将排序后的有序子文件(归并段)重新写回外存。

           2、对这些归并段进行逐趟归并,使归并段逐渐由小到大,直至得到整个有序文件。

若有N个记录,内存工作区可以容纳L个记录,则初始归并段数量r=N/L

以二路归并,2000个记录文件,每个磁盘块都含125条记录为例,共16个磁盘块:

1.初始归并段数量r=8。每个段含有250条记录。首先通过8次内部排序得到8个初始归并段R1~R8。

2.将8个归并段进行两两归并,直到得到一个有序文件

        假设把内存工作区等分为2个输入缓冲区,1个输出缓冲区。把R1,R2分别读入一个块,分别放在2个输入缓冲区中,在内存中对R1,R2进行归并排序,归并后的对象放在输出缓冲区中,若输出缓冲区满了,就将其顺序写到输出归并(R1`)段中,然后清空输出缓冲区,继续存放后续内容。若某个输入缓冲区取空了,则读取下一块,继续归并。

外部排序总时间=内部排序的时间+外存信息读/写的时间+内部归并的时间

如图所示,进行了三趟归并。内部排序读写次数=16+16。每趟需要读16次写16次。总共时间为32*3+32(内部排序的次数) 次读写。若增大归并路数,可减少归并趟数,进而减少总IO次数。

对r个初始归并段(先经过内部排序得到),做k路平衡归并。第一趟可以将r个初始归并段归并为\left \lceil r/k \right \rceil个归并段,依次类推,直至形成一个大的归并段为止。

归并趟数S=树的高度-1=\left \lceil log_{k}r \right \rceil

因此,增大归并路数k,或者减少初始归并段个数r(增大初始归并段长度),都能减少S

三、多路平衡归并与败者树

目的:减少关键字比较次数,减少归并趟数 

由归并排序可知,增加归并路数k能减少归并趟数s,进而减少io次数。但是增加归并路数k时,内部归并的时间也将增加。为使内部归并不受k的增大的影响,引入败者树,可视为完全二叉树

过程:k个叶节点分别存放k个归并段,内部结点记忆左右子树的失败者,让胜利者往上进行比较,一直到根节点。大者为失败者,小者为胜利者。根节点所指为最小数

k路归并的败者树深度为\left \lceil log_2{k} \right \rceil +1,则从k个记录中选择最小关键字,需\left \lceil log_2{k} \right \rceil次比较。

总的比较次数约为(n-1)\left \lceil log_2{r} \right \rceil

因此,使用败者树后,内部归并的比较次数与k无关。只要内存空间允许,增大归并路数k将有效减少归并树的高度,从而减少io次数,提高外部排序的速度

k不是越大越好,k增大时,相应地需要增加输入缓冲区的个数。若可供使用的内存空间不变,势必要减少每个输入缓冲区的容量,使得内存,外村交换数据的次数增大。当k过大时,虽然归并趟数会减少,但读写外存的次数仍会增加

四、置换-选择排序(生成初始归并段)

目的:减少初始归并段的数量

由归并排序可知,减少初始归并段个数r也能减少趟数,归并段的个数r=\left \lceil n/l \right \rceil n为记录数,l为每个归并段的长度,而每个初始归并段的长度是相同的,所以需要产生更长的初始归并段

实例见p397

五、最佳归并树

文件经过置换-选择排序后,得到的是长度不等的初始归并段。如何组织长度不等的初始归并段的归并顺序,使得io次数最少?

设各叶节点表示一个初始归并段,叶节点到根节点的路径长度表示参加归并的趟数,各非叶节点代表归并成的新归并段,根节点表示最终的归并段。则io次数=2*WPL

优化归并树的WPL:让记录数少的初始归并段最先归并,记录数最多的最晚归并。m路归并排序->m叉树

若初始归并段数不是m的整数倍,即不足以构成一个严格的m叉树,则需要添加长度为0的虚段,权为0的叶子应里根最远。

如何判定添加虚段的数目:

        设度为0的结点有n0个,度为k的结点有nk个,归并树的结点总数为n,则有

                n=nk+n0       n=k*nk+1     ->nk=(n0-1)/(k-1)

        若(n0-1)%(k-1)=0,说明这n0个叶节点正好可以构成k叉归并树,此时内节点有nk个。

        若=u≠0,说明有u个多余,不能包含在k叉归并树中。需加上k-u-1个空归并段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值