- 1、本文档共226页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8 外部排序 8 外部排序 8 外部排序 最佳归并树 数据结构考研复习4 * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8 外部排序 ? k?路归并 一般情况下,假设待排记录序列 含 m 个初始归并段,外排时采用 k?路归并,则归并趟数为 ?logkm?。 显然,随之k的增大归并的趟数将减少,因此对外排而言,通常采用多路归并。k 的大小可选,但需综合考虑各种因素。 8 外部排序 ?磁盘排序的例子 假设磁盘上存有一文件,共有3600个记录(A1, A2,…, A3600),页块长为200个记录,供排序使用的缓冲区可提供容纳600个记录的空间,现要对该文件进行排序。排序过程可按如下步骤进行: 8 外部排序 第一步,每次将三个页块(600个记录)由外存读到内存, 进行内排序,整个文件共得到6个初始顺串R1~R6 (每一个顺串占三个页块),然后把它们写回到磁盘上去。 8 外部排序 第二步, 二路归并 8 外部排序 ?多路归并的胜者树 8 外部排序 ?胜者树的修改 8 外部排序 讨论: ? 单纯增加k将导致内部归并排序时间tmg的增加。 ? 2-路归并,u个记录分布在两个归并段上,归并u个记录,需要u-1次比较。 ? k路归并,u个记录分布在k个归并段上,每选出一个最小记录,需比较k-1次;u个记录需(u-1)(k-1)次。 8 外部排序 ? n个记录,s趟,总比较次数 s (n-1)(k-1) ? 若初始归并段为m个,内部归并排序总比较次数为 分析:(k-1)/ log2k随k增加而增加。 8 外部排序 ? 解决办法:采用败者树,可使选择k个记录中的最小者仅需log2k次比较。 公式变为 ?log2m?(n-1) tmg 讨论:显然,此式与k无关。 8 外部排序 ?败者树 8 外部排序 ?败者树的修改 8 外部排序 ?败者树算法 void K_Merge (LoserTree ls, External b) { // 利用败者树ls将编号从0到k-1的k个输入归并段中的记录归并到输出归并段。 // b[0]至b[k-1]为败者树上的k个叶子结点,分别存放k个输入归并段中当前记录的关键字 8 外部排序 int i, q; for (i=0; ik; ++i) input(b[i].key, i); //分别从k个输入归并段读入该段 // 当前第一个记录的关键字到外结点 CreateLoserTree(ls); // 建败者树ls,选得最小关键字为b[ls[0]].key while (b[ls[0]].key != MAXKEY) { q = ls[0]; // q指示当前最小关键字所在输入归并段 8 外部排序 output(q); // 将编号为q的输入归并段中当前的记录写至输出归并段 input(b[q].key, q); // 从编号为q的输入归并段读入下一个记录的关键字 Adjust(ls, q); // 调整败者树,选择新的最小关键字 } output(ls[0]); // 将含最大关键字MAXKEY的记录写至输出归并段 } // K_Merge 8 外部排序 ?调整败者树算法 void Adjust(LoserTree ls, int s) { // 沿从叶子结点b[s]到根结点ls[0]的路径调整败者树。 int t, temp; t = (s+k)/2; // ls[t]是b[s]的双亲结点 while (t0) { if (b[s].key b[ls[t]].key) { temp = s; 8 外部排序 s = ls[t]; ls[t]
文档评论(0)