海量数据排序,多路平衡归并算法及实现(外部文件排序算法)

来源:互联网 发布:如何查询企业出口数据 编辑:程序博客网 时间:2024/05/16 23:44

外部文件多路平衡归并类似于内部排序的归并算法。可知增加分段个数k可以减少归并次数s,从而减少外存读写次数,但是单纯增加k将会导致增加内部归并的时间。
对于k-路归并,令u个记录分布在k个归并段上,显然,归并后的第一个记录应该是k个归并段中关键字最小的记录,即应从每个归并段的第一个记录的相互比较中选出最小者,这需要进行k-1次比较。同理,每得到归并后的有序段中的一个记录,就要进行k-1次比较。显然,为得到含u个记录的归并段需要进行(u-1)(k-1)次比较。由此,对n个记录的文件进行外部排序时,在内部归并过程中进行的总的比较次数为s(k-1)*(n-1)。由于随着k的增长,内部归并时间亦会增长,这将抵消掉由于增大k而减少外存信息读写时间所得的收益,这是我们所不希望的。然而,若在k-路归并时利用“败者树”,则可以使在k个记录中选出关键字最小的记录时仅需进行log2k次比较,从而使总的归并时间变小。
对于败者树的定义,请参考相关数据结构书籍,这里不作冗余叙述。
由于各路数据要防止归并过程中提前取空的问题,代码设计会有些变动,详见以下代码:

void k_merge(){    unsigned long int no;    int p;    double tempd;    for(int i=0;i<nfrag;i++)    {        p=poss[i];        fsortin.seekg((poss[i])*sizeof(double),std::ios::beg);        fsortin.read((char*)&tempd,sizeof(double));        external[i]=tempd;        poss[i]++;    }    create_losertree();    no=0;    while (no<maxnum)    {        p=losertree[0];        fsortout.write((char*)&(external[p]),sizeof(double));        no++;        if(poss[p]-p*maxnumin>=nums[p]){external[p]=MAXKEY;}        else        {            fsortin.seekg((poss[p])*sizeof(double),std::ios::beg);            fsortin.read((char*)&tempd,sizeof(double));            external[p]=tempd;            poss[p]++;        }        adjust(p);    }}void create_losertree(){    external[nfrag]=MINKEY;    for(int i=0;i<nfrag;i++) losertree[i]=nfrag;    for(int i=nfrag-1;i>=0;i--) adjust(i);}void adjust(int s){    int t=(s+nfrag)/2;    int temp;    while (t>0)    {        if(external[s]>external[losertree[t]])        {            temp=s;            s=losertree[t];            losertree[t]=temp;        }        t=t/2;    }    losertree[0]=s;}
0 0
原创粉丝点击