外部排序---置换选择+败者树

  当需要对一个大文件进行排序时,计算机内存可能不够一次性装入所有数据,解决办法是归并。归并的大概做法是将大文件分为若干段,依次读入内存进行排序,排序后再重新写入硬盘。这些排好序的片段成为顺串。然后对这些顺串进行逐躺归并,使归并段逐渐由小变大,最终使整个文件有序。要使用归并就得考虑两个问题,一个是如何生成顺串,一个是如何对顺串进行归并。

置换选择算法

  先考虑如何生成顺串。我们知道,减少顺串的数量可以降低归并的次数,而在文件大小固定的情况下,要减少顺串的数量,就要增大单个顺串的长度。如果使用内部排序生成顺串,那么顺串的大小最多等于可用内存的大小。因此我们使用置换选择排序,可以生成大概两倍于内存大小的顺串。步骤如下:

  (1)首先从输入文件中读取N个数字将数组填满  

  (2)使用数组中现有数据构建一个最小堆

  (3)重复以下步骤直到堆的大小变为0:

    a. 把根结点的数字A(即当前数组中的最小值)输出

    b. 从输入文件中再读出一个数字B,若R比刚输出的数字A 大,则将B放到堆的根节点处,若B不比A大,则将堆的最后一个元素移到根结点,将B放到堆的最后一个位置,并把堆的大小缩减1(即新读入的数据没有进入堆中)

    c. 在根结点处调用Siftdown重新维护堆

  (4)换一个输出文件,重新回到步骤(2)

书上有个铲雪机的例子来类比证明出使归并段长度的期望值为两倍工作区容量,但我觉得类比说明不了什么问题,严谨的证明我又不会,就跳过吧。

败者树

  接下来考虑如何对顺串进行归并。多路归并排序算法在常见数据结构书中都有涉及。从2路到多路(k路),增大k可以减少归并趟数,外存信息读写时间,但k个归并段中选取最小的记录需要比较k-1次,为得到u个记录的一个有序段共需要(u-1)(k-1)次,若归并趟数为s次,那么对n个记录的文件进行外排时,内部归并过程中进行的总的比较次数为s(n-1)(k-1),也即

而(k-1)/logk随k增而增因此内部归并时间随k增长而增长了,抵消了外存读写减少的时间,这样做不行,由此引出了“败者树”的使用。败者树只需进行logk次比较,在内部归并过程中利用败者树将k个归并段中选取最小记录比较的次数降为(logk)次使总比较次数为(logm)(n-1),与k无关。

败者树的具体操作《数据结构》书里有,我就不赘述了。这里说一下败者树和堆的比较。

堆执行一次比较(即调整)时间复杂度也是logn,但是堆调整的时候父节点要分别和两个子节点进行比较,而败者树只需和兄弟节点进行一次比较即可。因为要存储败者信息,败者树占用空间会比堆大。

  

时间: 2024-10-11 22:39:53

外部排序---置换选择+败者树的相关文章

排序(二)键索引、桶排序、位示图、败者树等

排序(二) 以上排序算法都有一个性质:在排序的最终结果中,各元素的次序依赖于它们之间的比较.我们把这类排序算法称为比较排序. 任何比较排序的时间复杂度的下界是nlgn. 以下排序算法是用运算而不是比较来确定排序顺序的.因此下界nlgn对它们是不适用的. 键索引计数法(计数排序) 计数排序假设n个输入元素中的每一个都是在0到k区间的一个整数,其中k为某个整数. 思想:对每一个输入元素x,确定小于x的元素个数.利用这一信息,就可以直接把x放到它在输出数组中的位置了. 例如: 学生被分为若干组,标号为

算法-排序(1)k路平衡归并与败者树

const int MaxValue=999; //根据实际情况选择最大值 void kwaymerge(Element *r,int k){ int i,q; r=new Element[k]; //在败者树中的k个记录 int *key=new int[k+1]; //k个排序码和建树单元key[k] int *loser=new int[k]; //k-1个败者和冠军loser[0] for(i=0; i<k; i++){ //从k个归并段输入第一个记录及其排序码 InputRecord(

数据结构实践——置换-选择算法模拟

本文是针对[数据结构基础系列(10):外部排序]中的实践项目. [项目 ]置换-选择算法模拟 编敲代码,模拟置换-选择算法生成初始归并段的过程. 设大文件里的记录共同拥有18个: 15 4 97 64 17 32 108 44 76 9 39 82 56 31 80 73 255 68 内存工作区能够容纳5个记录,输出产生的归并段文件. 在模拟中,输入文件数据和输出的归并段数据均直接置在内存中就可以. 參考解答 #include <stdio.h> #include <malloc.h&

外部排序-第11章-《数据结构题集》习题解析-严蔚敏吴伟民版

习题集解析部分 第11章 外部排序 ——<数据结构题集>-严蔚敏.吴伟民版        源码使用说明  链接??? <数据结构-C语言版>(严蔚敏,吴伟民版)课本源码+习题集解析使用说明        课本源码合辑  链接??? <数据结构>课本源码合辑        习题集全解析  链接??? <数据结构题集>习题解析合辑       相关测试数据下载  链接? 数据包       本习题文档的存放目录:数据结构\▼配套习题解析\▼11 外部排序    

数据结构实践项目——外部排序

本文是针对[数据结构基础系列(10):外部排序]中的实践项目. [项目-1]置换-选择算法模拟 编敲代码,模拟置换-选择算法生成初始归并段的过程. 设大文件里的记录共同拥有18个: 15 4 97 64 17 32 108 44 76 9 39 82 56 31 80 73 255 68 内存工作区能够容纳5个记录.输出产生的归并段文件. 在模拟中.输入文件数据和输出的归并段数据均直接置在内存中就可以. [參考解答] [项目2]败者树归并模拟 编敲代码,模拟改者树实现5路归并算法的过程. 设有5

外部排序&amp;多路归并排序

外部排序: 一.定义问题 外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序 整个文件的目的.外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序.然后,对已经排 序的子文件进行多路归并排序. 二.处理过程 (1)按可用内存的大小,把外存上含有n个记录的文件分成若干个长度为L的子文件,把这些子文件依次读入内存,并利用有效的内部排序方法对它们进行

外部排序总结

如果数据量过大,超过最大的内存容量,那么一次性将所有数据读入内存进行排序是不可行的. 例如,一个文件每一行存了一个整数,该文件大小为10GB,而内存大小只有512M,如何对这10GB的数据进行排序呢? 外部排序就是为了解决这种问题的. 思路: 外部排序的思路是,将超大文件分成若干部分,每一部分是可以读入内存的,例如,将10GB的文件分为40份,则每一份就只有256M.将每一份读入内存,用已知的方法进行排序(快拍,堆排等方式),再写到一个文件中.这样,我们得到了40个已序的小文件. 再采用归并(M

一篇能够加深对胜者树和败者树理解的文章

概念介绍 胜者树和败者树都是完全二叉树,是树形选择排序的一种变型.每个叶子结点相当于一个选手,每个中间结点相当于一场比赛,每一层相当于一轮比赛. 不同的是,胜者树的中间结点记录的是胜者的标号:而败者树的中间结点记录的败者的标号. 胜者树与败者树可以在log(n)的时间内找到最值.任何一个叶子结点的值改变后,利用中间结点的信息,还是能够快速地找到最值.在k路归并排序中经常用到. 胜者树 胜者树的一个优点是,如果一个选手的值改变了,可以很容易地修改这棵胜者树.只需要沿着从该结点到根结点的路径修改这棵

外部排序

部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的. 我们一般提到排序都是指内排序,比如快速排序,堆排序,归并排序等,所谓内排序就是可以在内存中完成的排序.RAM的访问速度大约是磁盘的25万倍,我们当然希望如果可以的话都是内排来完成.但对于大数据集来说,内存是远远不够的,这时候就涉及到外排序的知识了. http://zhidao.baidu.com/link?url=lUbNMEhPBlNk