2012版《数据结构高分笔记》更新补丁之外部排序

合集下载

排序之外部排序

排序之外部排序

排序之外部排序有时,待排序的⽂件很⼤,计算机内存不能容纳整个⽂件,这时候对⽂件就不能使⽤内部排序了(这⾥做⼀下说明,其实所有的排序都是在内存中做的,这⾥说的内部排序是指待排序的内容在内存中就可以完成,⽽外部排序是指待排序的内容不能在内存中⼀下⼦完成,它需要做内外存的内容交换),外部排序常采⽤的排序⽅法也是归并排序,这种归并⽅法由两个不同的阶段组成:1、采⽤适当的内部排序⽅法对输⼊⽂件的每个⽚段进⾏排序,将排好序的⽚段(成为归并段)写到外部存储器中(通常由⼀个可⽤的磁盘作为临时缓冲区),这样临时缓冲区中的每个归并段的内容是有序的。

2、利⽤归并算法,归并第⼀阶段⽣成的归并段,直到只剩下⼀个归并段为⽌。

例如要对外存中4500个记录进⾏归并,⽽内存⼤⼩只能容纳750个记录,在第⼀阶段,我们可以每次读取750个记录进⾏排序,这样可以分六次读取,进⾏排序,可以得到六个有序的归并段,如下图:每个归并段的⼤⼩是750个记录,记住,这些归并段已经全部写到临时缓冲区(由⼀个可⽤的磁盘充当)内了,这是第⼀步的排序结果。

完成第⼆步该怎么做呢?这时候归并算法就有⽤处了,算法描述如下:1、将内存空间划分为三份,每份⼤⼩250个记录,其中两个⽤作输⼊缓冲区,另外⼀个⽤作输出缓冲区。

⾸先对Segment_1和Segment_2进⾏归并,先从每个归并段中读取250个记录到输⼊缓冲区,对其归并,归并结果放到输出缓冲区,当输出缓冲区满后,将其写道临时缓冲区内,如果某个输⼊缓冲区空了,则从相应的归并段中再读取250个记录进⾏继续归并,反复以上步骤,直⾄Segment_1和Segment_2全都排好序,形成⼀个⼤⼩为1500的记录,然后对Segment_3和Segment_4、Segment_5和Segment_6进⾏同样的操作。

2、对归并好的⼤⼩为1500的记录进⾏如同步骤1⼀样的操作,进⾏继续排序,直⾄最后形成⼤⼩为4500的归并段,⾄此,排序结束。

外部排序处理大规模数据的外部存储排序算法

外部排序处理大规模数据的外部存储排序算法

外部排序处理大规模数据的外部存储排序算法在计算机科学中,外部排序是指对大规模数据进行排序时所采用的一种排序方式。

由于计算机内存的有限性,当数据量超过内存容量时,无法一次性加载到内存中进行排序。

因此,我们需要将数据分割成多个较小的块,在磁盘上进行排序,然后再将排序好的块逐个合并成最终有序的结果。

外部存储排序算法是一种用于处理大规模数据的高效排序算法,它充分利用了磁盘I/O的特性,以提高排序的效率和整体性能。

下面将介绍两种常见的外部存储排序算法:归并排序和多路归并排序。

一、归并排序归并排序是一种常见的排序算法,它也被广泛应用于外部存储排序中。

其基本思想是将待排序的数据划分为若干个子序列,分别进行内部排序,然后再将排好序的子序列进行合并,最终得到全局有序的结果。

归并排序的具体步骤如下:1. 将大规模数据划分成多个块并加载到内存中。

2. 对每个块进行内部排序,可以选择快速排序、堆排序等高效的排序算法。

3. 将排好序的块写入磁盘,同时将下一块数据加载到内存中。

4. 重复步骤2和步骤3,直到所有块都排序完毕。

5. 对排好序的块进行多路归并,生成最终的有序结果。

归并排序的时间复杂度为O(n log n),其中n表示待排序数据的总量。

它的优势在于适用于处理大规模数据,但由于需要频繁进行磁盘I/O,因此效率较低。

二、多路归并排序多路归并排序是一种改进版的归并排序算法,它能够同时合并多个有序的子序列,并生成一个更大的有序序列。

与传统的两路归并排序不同,多路归并排序可以合并超过两个的子序列。

多路归并排序的核心思想是使用最小堆来管理各个子序列的当前元素,每次从堆中选择最小的元素输出,并将其所在的子序列的下一个元素加入堆中。

通过不断地选择最小的元素,最终实现多路归并排序。

多路归并排序的具体步骤如下:1. 将大规模数据划分成多个块并加载到内存中。

2. 对每个块进行内部排序,可以选择快速排序、堆排序等高效的排序算法。

3. 将块的首个元素创建最小堆,并将最小堆中的元素输出到磁盘。

数据结构-C语言描述(第二版)课件:外部排序

数据结构-C语言描述(第二版)课件:外部排序

外部排序
磁盘的存取时间主要取决于寻查时间和等待时间。 磁 盘以2400~3600 r/min的速度旋转,因此平均等待时间约为 10 ms~20 ms, 而平均寻查时间约为几毫秒至几十毫秒,这 与CPU的处理速度相比较而言,仍是很慢的。因此,在讨论 外存的数据结构及其上的操作时,要尽量设法减少访问外存 的次数, 以提高磁盘存取效率。
第四步:把T1上的顺串1和T3上的顺串3合并,并把结 果放到T2
外部排序
上述例子采用的是2路归并法,与磁盘排序的情况一样, 排序的时间主要取决于对数据的扫描遍数。采用多路归并 能减少扫描的遍数,但对磁带排序来说,多路归并需要多 台磁带机,为了避免过多的磁带寻找时间,要归并的顺串 需要放在不同的磁带上。因此,k路归并至少需要k+1台磁 带机,其中k台作为输入带,另外一台用于归并后存放输出 结果。但这样需要对输出带再作一遍扫描,把输出带上的 各顺串重新分配到k台磁带上,以便作为下一级归并 使用。若使用2k台磁带机,则可避免这种再分配扫描,把k 台作为输入带,其余k台作为输出带,在下一级归并时,输 入带与输出带的作用互相对换。上述例子就是用4台磁带机 实现2路归并,T1、T2和T3、T4轮流地用作输入带和输出带。
外部排序 图10.2 活动臂示意图
外部排序
活动臂磁盘的磁头是安装在一个可活动臂上,随着活动 臂的移动, 磁头可在盘面上做同步的径向移动,从一个磁道 移到另一个磁道, 当盘面高速旋转,磁道在读/写头下通过 时,便可进行信息的读写。各记录盘面上半径相同的磁道合 在一起称为一个柱面, 柱面上各磁道在同一磁头位置下,即 活动臂移动时,实际上是把这些磁头从一个柱面移到另一个 柱面。 一个磁道内还可以分为若干段,称为扇段。因此,对 磁盘存储来说,由大到小的存储单位是: 盘片组,柱面,磁 道,扇段。以IBM2314型磁盘为例,其参数为:20个记录面 /磁盘组,200个磁道/记录面,7294字节/磁道。因此, 整个盘片组的容量为: 7294×200×200≈29 MB。

外部排序1-2

外部排序1-2

子序列为 “归并段”;
2.通过“归并”,逐步扩大(记录的)有序子序列
的长度,直至外存中整个记录序列按关键字有序为
止。
10
11.2
外部排序的方法
例如:假设有一个含10,000个记录的磁盘文件,而 当前所用的计算机一次只能对1,000个记录进行内 部排序,则首先利用内部排序的方法得到10个初始 归并段,然后进行逐趟归并。
一般情况下,假设待排记录序列含 m 个初始归并段,外排时 采用 k路归并,则归并趟数s=logkm,显然,随着k的增 大或m的减小,归并的趟数将减少,因此对外排而言,通常采 用多路归并。k 的大小可选,但需综合考虑各种因素。
14
11.3
多路平衡归并的实现
一、多路平衡归并的性质: •分析: m 个初始归并段,外排时采用 k路归并,则归 并趟数为 logkm , K 大,趟数减少,读写记录的总 数将减少。但 K 大,会使内部归并时间tmg增大?。
20
11.3 多路平衡归并的实现
三、败者树及其使用
ls [0]
0 ls[1] 3 ls[2] 0 5 ls[3] 1 9 2 7 3 29 4 5 5 7 6 29 7 9
4路平衡归并
1
b[1] 5 输 入
5 16 49 52 78
2
b[2] 29
29 38 57 66 71
b[0]
b[3] 9 注意:挑出冠军
二、胜者树及其使用
1
9 1 9 2 12 3 9 2 12 3 9 4 16 5 12 6 29 7 9
4路平衡归并
4 16 输 入
5 16 49 52 78
5 12
7 12 25 84 91
6 29

第十一章 外部排序

第十一章  外部排序
.
2
b1 9 9 18 20 . b2 20
3 4
b4 12 12 37 48 .
10
10 15 16 .
20 22 40 .ຫໍສະໝຸດ §11.4 置换-选择排序
• 问题: 是否可以不用内部排序构造初始归并段? • 例:若初始文件含有24个记录,其的关键字为: 51,49,39,46,38,29,14,61,15,1,48,52, 3,63,27,4,1389,24,46,58,33,76。 假设内存工作区可容纳6个记录,则可得如下4个初始 归并段: • RUN1:29,38,39,46,49,51 • RUN2:1,14,15,30,48,61 • RUN3:3,4,13,27,52,63 • RUN4:24,33,46,58,76,89
§11.3 多路平衡归并的实现
• 例:
3 1
胜利者
失败者
0
b0 b3 6 6 15 25
.
2
b1 9 9 18 20 . b2 20
4
b4 12 12 37 48 .
10
10 15 16 .
20 22 40 .
§11.3 多路平衡归并的实现
• 例:
1 3 0 1
胜利者
失败者
4 0
b0 b3 15 15 25
15,30,1,48,52,3,63,27,4,… 30,1,48,52,3,63,27,4,…
30,1,48,52,3,63,27,4,… 1,48,52,3,63,27,4,… 48,52,3,63,27,4,… 52,3,63,27,4,…
FO
29,38,39,46,49,51,61
WA
48,1,15,30,52,14 3,63,27,4,…

数据结构--排序算法介绍

数据结构--排序算法介绍

数据结构--排序算法总结概述排序的分类:内部排序和外部排序内部排序:数据记录在内存中进行排序外部排序:因排序的数据量大,需要内存和外存结合使用进行排序这里总结的八大排序是属于内部排序:当n比较大的时候,应采用时间复杂度为(nlog2n)的排序算法:快速排序、堆排序或归并排序。

其中,快速排序是目前基于比较的内部排序中被认为最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短。

———————————————————————————————————————————————————————————————————————插入排序——直接插入排序(Straight Insertion Sort)基本思想:将一个记录插入到已排序好的有序表中,从而得到一个新的,记录数增1的有序表。

即:先将序列的第1个记录看成一个有序的子序列,然后从第2个记录逐个进行插入,直至整个序列有序为止。

要点:设立哨兵,用于临时存储和判断数组边界直接插入排序示例:插入排序是稳定的,因为如果一个带插入的元素和已插入元素相等,那么待插入元素将放在相等元素的后边,所以,相等元素的前后顺序没有改变。

算法实现:[cpp]view plain copy1.#include<iostream>ing namespace std;3.4.void print(int a[], int n ,int i)5.{6. cout<<i<<":";7.for(int j= 0; j<8; j++){8. cout<<a[j] <<" ";9. }10. cout<<endl;11.}12.13.void InsertSort(int a[],int n)14.{15.int i,j,tmp;16.for(i=1;i<n;++i)17. {18.// 如果第i个元素大于第i-1个元素,直接插入19.// 否则20.// 小于的话,移动有序表后插入21.if(a[i]<a[i-1])22. {23. j=i-1;24. tmp=a[i]; // 复制哨兵,即存储待排序元素25. a[i]=a[i-1]; // 先后移一个元素26.while(tmp<a[j])27. {28.// 哨兵元素比插入点元素小,后移一个元素29. a[j+1]=a[j];30. --j;31. }32. a[j+1]=tmp; // 插入到正确的位置33. }34. print(a,n,i); // 打印每一趟排序的结果35. }36.}37.38.int main()39.{40.int a[8]={3,1,5,7,3,4,8,2};41. print(a,8,0); // 打印原始序列42. InsertSort(a,8);43.return 0;44.}分析:时间复杂度:O(n^2)———————————————————————————————————————————————————————————————————————插入排序——希尔排序(Shell Sort)基本思想:先将整个待排序的记录序列分割成为若干子序列,分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录依次进行直接插入排序。

外部排序技术之多路归并

外部排序技术之多路归并

外部排序技术之多路归并外部排序技术之多路归并重点:败者树的创建调整函数1.外部排序概述外部排序指的是⼤⽂件的排序,即待排序的记录存储在外存储器上,待排序的⽂件⽆法⼀次装⼊内存,需要在内存和外部存储器之间进⾏多次数据交换,以达到排序整个⽂件的⽬的。

外部排序最常⽤的算法是多路归并排序,即将原⽂件分解成多个能够⼀次性装⼈内存的部分,分别把每⼀部分调⼊内存完成排序。

然后,对已经排序的⼦⽂件进⾏归并排序。

2. 多路归并的实现2.1 胜者树胜者进⼊下⼀轮,直⾄决出本次⽐赛的冠军。

决出冠军之后,充分利⽤上⼀次⽐赛的结果,使得更快地挑出亚军、第三名 …… 。

⽰例:我们这⾥以四路归并为例,假设每个归并段已经在输⼊缓冲区如下图。

每路的第⼀个元素为胜利树的叶⼦节点,(5,7)⽐较出5胜出成为其根节点,(29,9)⽐较9胜出成为其根节点,⼀次向上⽣成⼀棵胜利树,然后我们可以得出5为冠军,将第⼀路归并段的元素5放⼊输出缓冲区,然后将第⼀路第⼆个元素放到胜利树中如下:由第⼀次得到的胜利树知,我们这⾥只改变了第1路的叶⼦节点,所有根节点7的右⼦树不⽤再⽐较,(16,7)⽐较7胜出,然后7和右⼦树的胜利者⽐较7胜出得到亚军,只进⾏了2次⽐较。

所以我们知道:决出第⼀名需⽐较: k - 1 次决出第⼆名需⽐较:次决出第三名需⽐较:次 .............2.2 败者树与胜利树相类似,败者树是在双亲节点中记录下刚刚进⾏完的这场⽐赛的败者,让胜者去参加更⾼⼀层的⽐赛。

⽰例:我们这⾥以四路归并为例,假设每个归并段已经在输⼊缓冲区如下图。

每路的第⼀个元素为胜利树的叶⼦节点,(5,7)⽐较出5胜出7失败成为其根节点,(29,9)⽐较9胜出29失败成为其根节点,胜者(5,9)进⾏下次的⽐赛7失败成为其根节点5胜出输出到输出缓冲区。

由第⼀路归并段输出,所有将第⼀路归并段的第⼆个元素加到叶⼦节点如下图:加⼊叶⼦节点16进⾏第⼆次的⽐较,跟胜利树⼀样,由于右⼦树叶⼦节点没有发⽣变化其右⼦树不⽤再继续⽐较。

数据结构之排序算法详解(含代码)

数据结构之排序算法详解(含代码)

C/C++版数据结构之排序算法今天讨论下数据结构中的排序算法。

排序算法的相关知识:(1)排序的概念:所谓排序就是要整理文件中的记录,使之按关键字递增(或者递减)次序罗列起来。

(2)稳定的排序方法:在待排序的文件中,若存在多个关键字相同的记录,经过排序后这些具有相同关键字的记录之间的相对次序保持不变,该排序方法是稳定的。

相反,如果发生改变,这种排序方法不稳定。

(3)排序算法的分类(分为5类):插入排序、选择排序、交换排序、归并排序和分配排序。

(4)排序算法两个基本操作:<1>比较关键字的大小。

<2>改变指向记录的指针或者挪移记录本身。

具体的排序方法:插入排序<1>插入排序(Insertion Sort)的思想:每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子记录中的适当位置,直到全部记录插入完成为止。

<2>常用的插入排序方法有直接插入排序和希尔排序。

(1)直接插入排序<1>算法思路:把一个记录集(如一个数组)分成两部份,前半部份是有序区,后半部份是无序区;有序区一开始有一个元素r[0],无序区一开始是从r[1]到之后的所有元素;然后每次从无序区按顺序取一个元素r[i],拿到有序区中由后往前进行比较,每次比较时,有序区中比r[i]大的元素就往后挪移一位,直到找到小于r[i]的元素,这时r[i]插到小元素的后面,则完成一趟直接插入排序。

如此反复,从无序区不断取元素插入到有序区,直到无序区为空,则插入算法结束。

<2>算法演示://直接插入排序:#include<iostream>using namespace std;void InsertSort(int r[],int n);int main(){int r[]={24,1,56,2,14,58,15,89};InsertSort(r,8);for(int i=0;i<8;i++){cout<<r[i]<<' ';}cout<<endl;return0;}void InsertSort(int r[],int n){for(int i=1;i<n;i++){for(int j=i-1,s=r[i];s<r[j] && j>=0;j--){r[j+1]=r[j];}r[j+1]=s;}}复制代码(2)折半插入排序<1>算法思路:我们看到在直接插入排序算法中,需要在有序区查找比r[i]的小的元素,然后插入到这个元素后面,但这里要注意这个元素是从无序区算第一个比r[i]小的元素。

外部排序---数据结构

外部排序---数据结构


将b[ls[0]]写至输出归并段 补充记录(某归并段变空时,补),调整败者树
算法描述:建立败者树
void CreateLoserTree() { b[k] = MINKEY; for (i = 0; i < k; i++) ls[i] = k; for (i = k - 1; i >= 0; i++) Adjust(i); } void Adjust(int s) { for (t = (s + k) / 2; t > 0; t /= 2) { if (b[s] > b[ls[t]]) s ls[t]; } ls[0] = s; }
外部排序的方法

由两个独立的阶段组成

将外存含n个记录的文件分成若干长度为l的子文件或段, 依次读入内存并用内部排序方法排序,将排序后的有 序子文件重新写入外存,称为归并段或顺串 对这些归并段进行逐趟归并,(有序子文件)由小变 大,直到获得整个有序文件

外排序基本方法:归并排序
[步骤] 生成若干初始归并串/顺串(文件预处理) 把含有n个记录的文件,按内存缓冲区大小分成若干长度为L 的子文件(段); 分别调入内存用有效的内排序方法排序后送回外存; 多路合并
外排序基本方法:归并排序

外存上的信息的读/写以“物理块”为单位,假设 每个物理块可容纳200个记录,则每一趟归并所 需进行50次“读”和50次“写”,4趟归并并加 上内部排序所需进行的读写使得外排序总共需进 行500读/写
外排序基本方法:归并排序

外部排序所需的总的时间= 内部排序所需的时间(m*tis) + 外存信息读写的时间(d*tio) + 内部归并所需的时间(s*utmg) tis::得到一个厨师归并段进行内部排序所需时间 tio:进行一次外存读/写所需时间 utmg:对u个记录进行内部归并所需的时间 m:经过内部排序后得到初始归并段的个数 s:为归并的趟数 d:为总的读/写次数

数据结构与算法系列——排序(15)_外部排序

数据结构与算法系列——排序(15)_外部排序

数据结构与算法系列——排序(15)_外部排序核⼼部分1. 实现外部排序的两个过程:1. 将整个初始⽂件分为多个初始归并段;2. 将初始归并段进⾏归并,直⾄得到⼀个有序的完整⽂件;2. 时间组成:1. 内部排序所需要的时间2. 外存信息读写所需要的时间(关键)与归并的趟数有关k要⼤ —– 传统⽅法会引起内部归并时间增⼤赢者树败者树(⽬的:提⾼在k个归并串中当前值中找到最⼩值的效率)m要⼩ —– 置换选择排序Huffman(归并的顺序,对外存的I/O次数降到最低)3. 内部归并所需要的时间 3. 为了提⾼整个外部排序的效率,分别从以上两个⽅⾯对外部排序进⾏了优化:1. 在实现将初始⽂件分为 m 个初始归并段时,为了尽量减⼩ m 的值,采⽤置换-选择排序算法(内部使⽤败者树实现),可实现将整个初始⽂件分为数量较少的长度不等的初始归并段。

2. 同时在将初始归并段归并为有序完整⽂件的过程中,为了尽量减少读写外存的次数,采⽤构建最佳归并树的⽅式(哈夫曼树实现),对初始归并段进⾏归并(败者树实现),⽽归并的具体实现⽅法是采⽤败者树的⽅式。

4. 优化递进顺序:1. ⼆路归并【因为硬盘的读写速度⽐内存要慢的多,按照以上这种⽅法,每个数据都从硬盘读了三次,写了三次,要花很多时间。

考虑K路】2. 多路归并【K不是越⼤越好,因为K越⼤,在内部排序需要的时间越长,效率低。

考虑减少初始顺串的数量M】3. 置换选择算法【可以⽤败者树和堆排序实现,得到多个长度不等的初始归并段,如何设置它们的归并顺序,可以使得对外存的访问次数降到最低? 考虑结合哈夫曼树】4. 最佳归并树(置换选择算法+哈夫曼树+多路归并+败者树)5 胜者树 & 败者树 & 堆排序发展历史 堆:其实⼀开始就是只有堆来完成多路归并的,但是⼈们发现堆每次取出最⼩值之后,把最后⼀个数放到堆顶,调整堆的时候,每次都要选出⽗节点的两个孩⼦节点的最⼩值,然后再⽤孩⼦节点的最⼩值和⽗节点进⾏⽐较,所以每调整⼀层需要⽐较两次。

外部排序分析

外部排序分析

外部排序分析当对数据记录量巨⼤的数据⽂件进⾏排序时,由于受到内存容量的限制,⽆法将所有数据记录⼀次全部读⼊到内存进⾏。

排序过程中需要多次进⾏内、外存之间的数据交换。

利⽤外存对数据⽂件进⾏排序称为外部排序。

外部排序最基本的⽅法是归并。

这种⽅法是由两个相对独⽴的阶段组成:①按内存(缓冲区)的⼤⼩,将n个记录的数据⽂件分成若⼲个长度为l的段或⼦⽂件,依次读⼊内存并选择有效的内部排序⽅法进⾏排序;然后将排好序的有序⼦⽂件重新写⼊到外存。

⼦⽂件称为归并段或顺串。

②采⽤归并的办法对归并段进⾏逐趟归并,使归并段的长度逐渐增⼤,直到最后合并成只有⼀个归并段的⽂件—排好序的⽂件。

1 外部排序的简单⽅法归并排序有多种⽅法,最简单的就是2-路归并。

设有⼀个磁盘上的数据⽂件,共有100,000个记录(A1, A2,…,A100000),页块长为200个记录,供排序使⽤的缓冲区可提供容纳1000个记录的空间,现要对该⽂件进⾏排序,排序过程可按如下步骤进⾏:第⼀步:每次将5个页块(1000个记录)由外存读到内存,进⾏内排序,整个⽂件共得到10个初始顺串R1~R10 (每⼀个顺串占5个页块),然后把它们写回到磁盘上去。

第⼆步:然后两两归并,直到成为⼀个有序⽂件为⽌。

由图可知,每趟归并由m个归并段得到┌m/2┐个归并段。

2 外排序的时间分析外排序的时间消耗⽐内排序⼤得多,原因是:●外排序的数据量(记录)⼀般很⼤;●外排序涉及到内、外存之间的数据交换操作;●外存的操作速度远远⽐内存中的操作慢。

外排序的总时间由三部分组成:外排序的时间=产⽣初始归并段的时间(内排序)m×tis+I/O操作的时间d×tio+内部归并的时间s×utmg其中:m:初始归并段数⽬;tis:得到⼀个归并段的内排序时间;d:总的读、写次数;tio:⼀次读、写的时间;s:归并的趟数;utmg:对u个记录进⾏⼀趟内部归并排序的时间。

⼀般地,tio>>tis,tio>>tmg,tio⽽取决于所⽤外存,因此,影响外排序效率的主要原因是内、外存之间数据交换(读、写外存)。

【数据结构】排序——外部排序

【数据结构】排序——外部排序

【数据结构】排序——外部排序【数据结构】排序——外部排序外部排序是指⼤⽂件的排序,即排序的记录存储在外存储器上,在排序过程中需进⾏多次的内、外存之间的交换。

外部排序⽅法通常采⽤归并排序有外部排序基本上由两个相对独⽴的阶段组成。

按可⽤内存⼤⼩,将外存上含有n个记录的⽂件分成若⼲长度为l的字⽂件或段。

依次读⼊内存并利⽤有效的内部排序⽅法排序,将排序后得到的有序⼦⽂件(称为归并段或顺串),进⾏逐趟归并,直⾄得到整个有序⽂件为⽌。

在外部排序中实现两两归并,由于不可能将两个有序段及归并结果段同时存放在内存中的缘故,所以不仅要调⽤归并过程,还需要进⾏外存的读_写(对外存上信息的读_写是以“物理块”为单位的)。

耗费时间总时间=内部排序时间(产⽣初始归并段)+外存读写时间+内部归并时间内部排序时间=经过内部排序后得到的初始归并段的个数r * 得到⼀个初始归并段进⾏内部排序多需时间的均值外存读写时间=总的读写次数 * 进⾏⼀次外存读写时间的均值内部归并时间=归并的趟数s * n个记录进⾏内部归并排序的时间优化⽅法增⼤归并路数k减少初始归并段个数r以上两个⽅法都可以减少归并的趟数,进⽽减少读写磁盘的次数,提⾼外部排序速度多路平衡归并与败者树已知增加k可以减少s,从⽽减少总的读写次数。

如果只单纯的增加k⼜会导致内部归并时间增加。

为了使内部归并不受k的增⼤⽽影响,提出了败者树。

败者树的基本思想败者树是树形选择排序的⼀种变型,可视为⼀棵完全⼆叉树。

k个叶⼦节点分别存放k个归并段在归并过程中当前参加⽐较的记录,内部节点⽤来记忆左右⼦树中的“失败者”,⽽让胜者往上继续进⾏⽐较,⼀直到根结点。

若⽐较两个数,⼤的为败者、⼩的为胜利者,则根结点指向的数为最⼩数。

eg、设初始归并段为(10,15,31),(9,20),(6,15,42),(12,37),(84,95),利⽤败者树进⾏m路归并,⼿⼯执⾏选择最⼩的5个关键字的过程。

性能分析k-路归并的败者树的深度为[log2k]+1注意⚠ 在多路平衡归并中采⽤简单⽐较时,k越⼤,关键字的⽐较次数会越⼤。

数据结构11-外部排序

数据结构11-外部排序

例: 5 - 路平衡归
并的败者树:
[0] 531 [1] 510
[2] 5304
[3] 52
[4] 543
b0 12 b1 1805 b2 30
b3 b4 253 16
12 1805 30 14 12059 38
253 16 17 128598 56
b5
2334
0 3448
28 31
初始归并段
5
8 10 …
磁盘是在一片塑料薄膜上涂有磁性材料用以记 录数据的存储介质。它分成多个磁道(柱面),每 个磁道又分为多个扇区,多个磁盘组成的磁盘组还 涉及到盘片号(磁头号),磁盘绕轴高速旋转,读 写头则沿其一条半径作直线运动以寻道。它也不是
连续运转的设备,读写信息只能在旋转稳定时进行, 且找到要读写的记录也需要一定的寻道、寻扇区时 间,因此,在磁盘上读写信息所需的时间由三部分 组成:TI/O = tseek + tla + n tw,其中 tseek 为寻道时间 (seek time), tla 为寻扇区时间(latency time time), tw 为传输时间(transmission time)。磁盘 是一种随机存储设备。
§11.6 最佳归并树
用置换-选择排序得到的初始归并段长度各不相 同,那应如何进行 k 路平衡归并呢?这实际上是建立 k 叉霍夫曼树的问题:当初始归并段总数不足( ( m 1 ) MOD ( k - 1 ) ≠ 0 )时,需附加 k - ( m - 1 ) MOD ( k - 1 ) -1 个长度为零的虚段,亦即第一次归并时只 对 ( m - 1 ) MOD ( k - 1 ) + 1 个初始归并段归并。建 立 k 叉霍夫曼树每次仍是选择记录数相对少的初始归 并段先进行归并。最佳归并树不适合磁带归并排序。

解决大规模数据问题的外部排序算法

解决大规模数据问题的外部排序算法

解决大规模数据问题的外部排序算法外部排序是一种处理大规模数据的排序算法,由于内存限制,无法将所有数据加载到内存中进行排序。

所以,外部排序利用磁盘空间来进行数据的划分和排序,以解决大规模数据问题。

本文将介绍一种常用的外部排序算法——多路归并排序。

一、多路归并排序概述多路归并排序是一种基于分治思想的排序方法,它将大规模数据划分为多个小块,并在磁盘上对这些小块进行排序。

然后,再将排好序的小块进行归并,最终得到完整有序的数据。

多路归并排序多用于外排序,其主要特点是能够处理大规模数据,并且排序效率较高。

二、多路归并排序的实现步骤1. 数据划分首先,将大规模数据划分为多个小块。

可以通过读取数据集并将其划分为大小相等的块,每个块的大小受到内存大小的限制。

2. 内部排序对每个小块进行内部排序,常用的内部排序算法包括快速排序、归并排序、堆排序等。

选择合适的内部排序算法,将小块排序后存放在磁盘中。

3. 多路归并将排好序的小块进行多路归并。

多路归并即将多个有序的序列合并为一个有序序列。

在多路归并中,可以借助最小堆等数据结构,每次从多个序列中选择最小的元素,加入到有序序列中。

4. 写出结果将最终得到的有序序列写出到磁盘文件中。

三、多路归并排序算法的优化1. 外部排序的前提是磁盘I/O的次数尽可能少,因此可以采用合适的数据结构来减少读写次数,如B+树等。

2. 利用多线程或多进程进行归并操作可以加快排序速度。

可以将原始数据划分为多个小块,并利用多个线程或进程分别对这些小块进行排序和归并。

3. 预读数据是提高排序效率的一个关键。

可以采用预读技术,提前将数据加载到内存缓冲区中,减少磁盘I/O的次数。

4. 考虑数据的分布情况进行数据划分。

如果数据是有序的,可以将其均匀划分到不同的小块中,以充分利用有序性。

四、总结多路归并排序是一种有效解决大规模数据问题的外部排序算法。

通过将数据划分为多个小块,并采用多路归并的方式进行排序,可以充分利用磁盘空间和减少磁盘I/O次数。

数据结构-外部排序

数据结构-外部排序

11-11
3 多路平衡归并的实现
• 对于2路归并, 令两个归并段上有u个记录, 每得到 归并后的一个记录, 仅需一次比较即可, 因此得到 含u个记录的归并段需进行u-1次比较。 • 对于k路归并, 令u个记录分布在k个归并段上, 显 然, 归并后的第一个记录应是k个归并段中关键字 最小的记录, 这需要进行k-1次比较, 得到u个记录 的归并段, 共需(u-1)(k-1)次比较。由此, 对n个记录的 文件进行外排序时, 在内部归并过程中进行的总的 比较次数为s(k-1)(n-1)。假设所得初始归并段为m个, 则 归并过程中进行比较的总的时间为:
结果:采用胜者树后, 从 k 个元素中挑选一个最小的元素仅需 log2k 次比较, 这时总的比较次数下降为:
logkm × log2k × ( n - 1 ) × tmg = log2m × ( n - 1 ) × tmg
该结果和 k 无关, 这是通过多用空间换来的。 • 改进:采用胜者树, k个元素中最小的元素输出之后, 从根结点到 它的相应的叶子结点路径上的结点都需要进行修改, 为了加快程 序运行的速度产生了败者树。
11-16
3 多路平衡归并的实现
• 败者树 在父节点中记下刚进行完的比赛中的败者, 但同样让胜者去参加下一轮的竞赛, 便得 到一棵“败者树”。
11-17
3 多路平衡归并的实现
• 下图即为一棵实现5-路归并的败者树ls[0…4], 图 中方形结点表示叶子结点(也可看成是外结点), 分 别为5个归并段中当前参加归并的待选择记录的关 键码;败者树中根结点ls[1]的双亲结点ls[0]为 “冠军”, 在此指示各归并段中的最小关键码记录 为第三段中的记录;结点ls[3]指示b1和b2两个叶 子结点中的败者即是b2, 而胜者b1和b3(b3是叶子 结点b3、b4和b0经过两场比赛后选出的获胜者)进 行比较, 结点ls[1]则指示它们中的败者为b1。

数据结构(十)外部排序

数据结构(十)外部排序
13 11 8
12
6 12 7 14
7
15 13
26
8 24 11
问题:当一个三角形塔给出后,找出一条从根到底层的路径, 使路径上的值最大。
分析: (1)贪心法往往得不到最优解
13
11
12 6 12 7 14 13 7
8
26 15 24 8 11
分析: (1)贪心法往往得不到最优解
13
11
12 6 12 7 14 13 7
如果问题的所有可能答案,都可以在多项式时间内进行正确 与否的验算的话,就叫完全多项式非确定问题。完全多项式非 确定性问题可以用穷举法得到答案,一个个检验下去,最终便 能得到结果。但是这样算法的复杂程度,常常是指数关系,因 此计算的时间随问题的复杂程度成指数的增长,很快便变得不
可计算了。
有大量问题具有以下特性:知道有效的非确定性算法, 但是不知道是否存在有效的确定性算法,同时,不能证明 这些问题中的任何一个不存在有效的确定性算法。这类问 题称为NP完全问题。
本课程许多算法都是多项式时间,即对规模为n 的输入,算法在最坏情况下的计算时间是O(nk),k是 常数。
一个问题称为是P的,如果它可以通过运行多项式 次(即运行时间至多是输入量大小的多项式函数的一种 算法获得解决)。----确定性问题
并不是所有问题都在多项式时间内可解的。在可计算 性理论中,著名的“图灵停机问题”,任何计算机不论 耗费多少时间也不可能解决该问题。 有写问题,虽然可以用计算机求解,但是对于任意常 数k,它们不能在O(nk)时间内得到解答。 ————非确定性问题
void output(St g[][NUM],int n) { int i,j; int mm=0; for(i=0;i<NUM;i++) { for(j=0;j<=i;j++) cout<<setw(3)<<g[i][j].val<<' '; cout<<endl;} cout<<g[0][0].val; j=0; for(i=0;i<n-1;i++) { j+=g[i][j].de; mm+=g[i+1][j].val; cout<<"->"<<g[i+1][j].val; } cout<<':'<<mm<<endl; }

外部排序---数据结构

外部排序---数据结构

外部排序---数据结构外部排序数据结构在计算机科学中,数据的排序是一项非常基础且重要的操作。

当数据量过大,无法一次性全部放入内存进行排序时,就需要用到外部排序这种技术。

想象一下,你有一个巨大的数据集,大到内存根本装不下。

这时候,内部排序算法,比如快速排序、冒泡排序等等,就显得无能为力了。

外部排序就像是一位超级英雄,专门来解决这种内存装不下的大问题。

外部排序的基本思路其实并不复杂,但实现起来却需要一些巧妙的策略。

它通常会将数据分成多个较小的部分,先在内存中对这些小部分进行排序,然后将排序好的小部分逐次合并,最终得到完全有序的数据。

为了更好地理解外部排序,让我们先来看看它的工作流程。

假设我们有一个非常大的文件需要排序,由于内存限制,我们不能一次性把整个文件读入内存。

所以,第一步就是将这个大文件分割成若干个大小适中的子文件,这些子文件能够被轻松地读入内存。

然后,我们在内存中使用一种内部排序算法,比如快速排序,对每个子文件进行单独排序。

接下来就是关键的合并步骤。

我们会从已经排序好的子文件中依次读取数据,然后将它们合并到一个新的文件中。

这个合并的过程就像是把几堆已经排好序的扑克牌重新整理成一整堆有序的扑克牌。

在合并的过程中,我们需要不断地比较来自不同子文件的数据,将较小的数据先放入新文件中。

那么,在这个过程中,有哪些关键的技术和要点呢?首先是数据的分割策略。

我们要确保分割出来的子文件大小合适,既能在内存中高效处理,又不会导致分割次数过多而增加额外的开销。

如果子文件分得太小,那么合并的次数就会增多,效率就会降低;如果分得太大,又无法在内存中进行排序。

其次是内存的使用。

在外部排序中,内存的使用需要非常精细地管理。

我们不仅要为读取和写入数据留出空间,还要为中间的比较和合并操作保留足够的缓冲区。

如果内存使用不当,可能会导致频繁的磁盘读写,大大降低排序的速度。

还有就是合并算法的选择。

常见的合并算法有二路归并和多路归并。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

※特别章外部排序(2012版《数据结构高分笔记》更新补丁)
·外部排序简介
所谓外部排序,即对外存中的数据进行排序(相对于内部排序而言),也可以说是对文件中的数据进行排序。

有了内部排序算法,为什么还要外部排序?因为文件太大,内存放不下。

外排做法可以概括为一句话:将内存作为工作空间来调整外存中数据的位置。

具体可以分成以下三个要点:
①文件在外存中的组织;
②文件在内存中的排序;
③文件在内外存之间的交换。

说明:本补丁是2012年数据结构考研大纲新增内容,虽然知识点不多,但由于第一年被列入考试范围,所以大家要重视。

·归并排序法
归并排序法是外排序中最常用的方法,分为两个执行阶段。

第一阶段:将文件中的数据分段输入到内存中,在内存中用内排序方法对其分类,这样排序完的文件段称作归并段,然后将其写回外存中而在外存中形成了许多初始归并段。

第二阶段:对这些初始归并段采用某种归并方法,进行多遍归并,最后在外存上形成整个文件的单一归并段,也就完成了这个文件的外排序。

说明:外排序中的归并排序法和内排序中的归并法是类似的,都是由小单元逐渐归并成单元的过程,注意对比,加深理解。

归并排序算法分两个阶段:
1.初始归并段的形成
其过程是根据缓冲区大小,由文件输入(由外存读入内存)记录,当记录充满缓冲区后,选择最小的(以递增排序为例)记录输出(由内存写出到外存),其空缺位置由下一个输入记录来取代,输出的记录成为当前初始归并段的一部分。

如果新输入的记录不能成为当前生成的归并段的一部分,即它比生成的当前部分归并段最大的记录要小(如例1中的关键字11,比15要小,不可能出现在当前归并段中),它将等待生成下一个归并段时提供选择。

反复进行上述操作,直到所有新输入的记录关键字都小于最后输出记录的关键字时(如步骤9中的所有关键字都比83小,则以83为结尾的归并段生成完毕),就生成了一个初始归并段。

接着继续生成下一个归并段,直到全部记录都处理完毕为止。

下面通过例题来具体说明一下。

例1.设输入文件的各个记录的关键字为:
15,19,04,83,12,27,11,25,16,34,26,07,10,90,06, ... ...
假设内存缓冲区可容纳4个记录,成初始归并段。

如下表所示,给出了生成初始归并段过程中各步的缓冲区内容和输出结果。



1 2 3 4 5 6 7 8 9 10 11 12 13 ...
缓冲区内容15 15 15 11 1111111111 11 11 06 ......
19 19 19 19 25161616
16 16 16 16 ......
04 12 27 27 2727342626 26 26 26 ......
83 83 83 83 8383838307 10 90 90 ......
输出结果
04 12 15 19 25 27 34 83 07 10 11 06 ... ...
所生成的第一初始归并段所生成的第二初始归并段
... ...
初始归并段生成过程表(表中下划线数字即为生成下一归并段的候选数字)
2. k路归并
有了m个初始归并段(都是有序段),便可以进行k路归并了,即将k个初始归并段
归并产生一段,这样,m个初始归并段产生多个这样的段,然后对这些段再用同样的方法进行归并,如此往复,直到归并成一个段为止,这个段就是最后生成的归并段。

例2.一个文件,含有10000个记录,通过1.1中介绍的方法,得到10个初始归并段R1... R10,其中每一个段都含有1000个记录。

外存上的信息读/写是以物理块为单位进行的,假设每个物理块可以容纳200个记录,则每一趟归并需要进行50次读和50次写,4趟归并加上内部排序所需要进行的读/写使得在外排序中总共需要进行500次读/写。

对初始归并段做两两归并:
R1,R2 R3,R4 R5,R6 R7,R8 R9,R10 R1’ R2’ R3’ R4’ R5’
R1” R2” R3”
R1’’’ R2’’’
R1’’’’(有序文件)
每次都由m个归并段得到个归并段,这种归并方法称为2-路归并。

若对上例进行5-路归并则有:
R1,R2,R3,R4,R5 R6,R7,R8,R9,R10
R1” R2”
R1’’’(有序文件)
·归并排序时间复杂度分析
m个初始归并段进行k路归并,归并的遍数为。


理的时间,而归并遍数为,所。

图1
(2)第一次比较胜出者5与第三个叶子结点10比较,10为败者,5为胜者,因而10替换到5的位置,5作为胜者向上一级比较,如图2
图2
(3)同理,依次比较其他各叶子结点,最终得到第一棵败者树为:
图3
K路归并的败者树的深度⎡log2k⎤在每次调整查找下一个具有最小关键字记录时,最多做⎡log2k⎤次关键字比较。

因此,利用败者树在K个记录中选择最小者,时间复杂度为O(log2k)。

说明:败者树和其他选择树的原理都是一样的,比如之前堆排序中的堆。

做法都是先用一个较大的时间复杂度将待排元素建成一棵满足一定要求的树,然后就可以从中取出一个满足要求的元素,并将新来的元素放在刚取出元素的位置上;这样只会在一点上对树的结构造成破坏而不会造成全局的破坏,因此只需花较小的时间复杂度进行局部调整即可将被破坏的结构恢复正常,无需从新建树。

局部调整即可恢复结构从而降低时间复杂度,这就是选择树的精髓。

数据结构就是这样,其实各种乱七八糟的结构都是表象,浮云,其背后的本质就那么一点,懂了这个之后,数据结构学习就会很轻松,最后祝大家考研愉快。

习题心选:
一、选择题:
1.外排序是指()
A.在外存上进行的排序方法。

B.不需要使用内存的排序方法。

C.数据量大,需要人工干预的排序方法。

D.排序前后数据在外存,排序时数据调入内存的排序方法。

2.文件有m个初始归并段,采用k路归并时,所需的归并遍数是()
A.log2k
B.log2m
C.log k
m D.
1 2 3 4 5 6 7 8 9 10 11
缓冲区内容10 12 13 21 21 21 16 16 16 16 20 20 20 20 20 8 8 8
15 15 15 15 30 30 30 30
25 25 25 25 25 25 25 10 10
输出结果10 12 13 15 20 21 25 30 8 10 16
第一初始归并段第二初始归并段
本题简单,每次从缓冲区中选出最小且比当前归并段最大的元素还要大的输出,空出来的位置读入新的关键字(参照例1 解法)。

2.答:内部排序中的归并排序是在内存中进行的归并排序,辅助空间为O(n)。

外部归并排序是将外存中的多个有序子文件合并成一个有序子文件,将每个子文件中记录读入内存后的排序方法可采用多种内排序方法。

外部排序的效率主要取决于读写外存的次数,即归并的趟数。

因为归并的趟数s=⎡log k m⎤,其中,m是归并段个数,k是归并路数。

增大k和减少m 都可减少归并趟数。

应用中通过败者树进行多(k)路平衡归并和置换-选择排序减少m,来提高外部排序的效率。

相关文档
最新文档