• 败者树 K路归并排序 天堂人间 博客频道 CSDN.NET


    败者树 K-路归并排序 - 天堂人间 - 博客频道 - CSDN.NET

    败者树 K-路归并排序

    分类: 算法学习 排序 628人阅读 评论(0) 收藏 举报
     

     

             外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行多路归并排序。

        多路归并排序算法在常见数据结构书中都有涉及。从2路到多路(k路),增大k可以减少外存信息读写时间,但k个归并段中选取最小的记录需要比较k-1次,为得到u个记录的一个有序段共需要(u-1)(k-1)次,若归并趟数为s次,那么对n个记录的文件进行外排时,内部归并过程中进行的总的比较次数为s(n-1)(k-1),也即(向上取整)(logkm)(k-1)(n-1)=(向上取整)(log2m/log2k)(k-1)(n-1),而(k-1)/log2k随k增而增因此内部归并时间随k增长而增长了,抵消了外存读写减少的时间,这样做不行,由此引出了“败者树”tree of loser的使用。在内部归并过程中利用败者树将k个归并段中选取最小记录比较的次数降为(向上取整)(log2k)次使总比较次数为(向上取整)(log2m)(n-1),与k无关。

            败者树是完全二叉树,因此数据结构可以采用一维数组。其元素个数为k个叶子结点、k-1个比较结点、1个冠军结点共2k个。ls[0]为冠军结点,ls[1]--ls[k-1]为比较结点,ls[k]--ls[2k-1]为叶子结点(同时用另外一个指针索引b[0]--b[k-1]指向)。另外bk为一个附加的辅助空间,不属于败者树,初始化时存着MINKEY的值。

        多路归并排序算法的过程大致为:首先将k个归并段中的首元素关键字依次存入b[0]--b[k-1]的叶子结点空间里,然后调用CreateLoserTree创建败者树,创建完毕之后最小的关键字下标(即所在归并段的序号)便被存入ls[0]中。然后不断循环:把ls[0]所存最小关键字来自于哪个归并段的序号得到为q,将该归并段的首元素输出到有序归并段里,然后把下一个元素关键字放入上一个元素本来所在的叶子结点b[q]中,调用Adjust顺着b[q]这个叶子结点往上调整败者树直到新的最小的关键字被选出来,其下标同样存在ls[0]中。循环这个操作过程直至所有元素被写到有序归并段里。

    以上资料借鉴 http://chenkegarfield.blog.163.com/blog/static/62330008200910249526638/

    参考数据结构(C语言版)严蔚敏教材P298页伪代码,用C++实现

    代码如下:

     

    1. #include <iostream>  
    2. using namespace std;  
    3.   
    4. #define LEN 10          //最大归并段长  
    5. #define MINKEY -1     //默认全为正数  
    6. #define MAXKEY 100    //最大值,当一个段全部输出后的赋值  
    7.   
    8. struct Array  
    9. {  
    10.     int arr[LEN];  
    11.     int num;  
    12.     int pos;  
    13. }*A;  
    14.   
    15.     int k,count;  
    16.     int *LoserTree,*External;  
    17.   
    18. void Adjust(int s)  
    19. {  
    20.     int t=(s+k)/2;  
    21.     int temp;  
    22.     while(t>0)  
    23.     {  
    24.         if(External[s] > External[LoserTree[t]])  
    25.         {  
    26.             temp = s;  
    27.             s = LoserTree[t];  
    28.             LoserTree[t]=temp;  
    29.         }  
    30.         t=t/2;  
    31.     }  
    32.     LoserTree[0]=s;  
    33. }  
    34.   
    35. void CreateLoserTree()  
    36. {  
    37.     External[k]=MINKEY;  
    38.     int i;  
    39.     for(i=0;i<k;i++)LoserTree[i]=k;  
    40.     for(i=k-1;i>=0;i--)Adjust(i);  
    41. }  
    42.   
    43. void K_Merge()  
    44. {  
    45.     int i,p;  
    46.     for(i=0;i<k;i++)  
    47.     {  
    48.         p = A[i].pos;  
    49.         External[i]=A[i].arr[p];  
    50.         //cout<<External[i]<<",";  
    51.         A[i].pos++;  
    52.     }  
    53.     CreateLoserTree();  
    54.     int NO = 0;  
    55.     while(NO<count)  
    56.     {  
    57.         p=LoserTree[0];  
    58.         cout<<External[p]<<",";  
    59.         NO++;  
    60.         if(A[p].pos>=A[p].num)External[p]=MAXKEY;  
    61.         else   
    62.         {  
    63.             External[p]=A[p].arr[A[p].pos];  
    64.             A[p].pos++;  
    65.         }  
    66.         Adjust(p);  
    67.     }  
    68.     cout<<endl;  
    69. }  
    70.   
    71. int main()  
    72. {  
    73.     freopen("in.txt","r",stdin);  
    74.   
    75.     int i,j;  
    76.     count=0;  
    77.     cin>>k;  
    78.     A=(Array *)malloc(sizeof(Array)*k);  
    79.     for(i=0;i<k;i++)  
    80.     {  
    81.         cin>>A[i].num;  
    82.         count=count+A[i].num;  
    83.         for(j=0;j<A[i].num;j++)  
    84.         {  
    85.             cin>>A[i].arr[j];  
    86.         }  
    87.         A[i].pos=0;  
    88.     }  
    89.     LoserTree=(int *)malloc(sizeof(int)*k);  
    90.     External=(int *)malloc(sizeof(int)*(k+1));  
    91.   
    92.     K_Merge();  
    93.   
    94.     return 0;  
    95. }  

    输入文件 如下:

    5
    5
    1 5 6 8 25
    6
    2 6 9 25 30 32
    3
    5 9 16
    6
    6 9 15 24 30 36
    2
    8 34

  • 相关阅读:
    网上找的,C# 小票打印机 直接打印,备用
    SlickUpload 破解方法
    全文索引的一点个人总结
    在ASP.NET中利用SlickUpload来上传大文件
    再谈iframe自适应高度 By 大米
    发送邮件到 163、Gmail、QQ 等邮箱时,全丢垃圾箱中怎么办?
    iis下Awstats的安装使用说明
    AutoCompleteExtender控件出现undefined和null现象
    IT业史上最棒的图片之一
    EnableViewState="false",取dropdownlist的值
  • 原文地址:https://www.cnblogs.com/lexus/p/2951886.html
Copyright © 2020-2023  润新知