• 败者树


    大文件排序

    #include <stdio.h>
    #define k 5
    #define MAXKEY 10000
    #define MINKEY -1
    typedef int LoserTree[k];//表示非终端结点,由于是完全二叉树,所以可以使用一维数组来表示
    typedef struct {
        int key;
    }ExNode, External[k + 1];
    External b;//表示败者树的叶子结点
    //a0-a4为5个初始归并段
    int a0[] = { 10,15,16 };
    int a1[] = { 9,18,20 };
    int a2[] = { 20,22,40 };
    int a3[] = { 6,15,25 };
    int a4[] = { 12,37,48 };
    //t0-t4用于模拟从初始归并段中读入记录时使用
    int t0 = 0, t1 = 0, t2 = 0, t3 = 0, t4 = 0;
    //沿从叶子结点b[s]到根结点ls[0]的路径调整败者树
    void Adjust(LoserTree ls, int s) {
        int t = (s + k) / 2;//叶子结点对应根节点下标
        while (t > 0) {
            //判断每一个叶子结点同其双亲结点中记录的败者的值相比较,调整败者的值,其中 s 一直表示的都是胜者
            if (b[s].key > b[ls[t]].key) {//最开始,ls[t]是k,b[k]是MINKEY
                int swap = s;
                s = ls[t];
                ls[t] = swap;
                //ls[t] = s;
            }
            t = t / 2;
        }
        //最终将胜者的值赋给 ls[0]
        ls[0] = s;
    }
    //创建败者树
    void CreateLoserTree(LoserTree ls) {
        b[k].key = MINKEY;
        //设置ls数组中败者的初始值
        for (int i = 0; i < k; i++) {
            ls[i] = k;
        }
        //对于每一个叶子结点,调整败者树中非终端结点中记录败者的值
        for (int i = k - 1; i >= 0; i--) {
            Adjust(ls, i);
        }
    }
    
    //模拟从外存向内存读入初始归并段中的每一小部分
    void input(int i) {
        switch (i) {
        case 0:
            if (t0 < 3) {
                b[i].key = a0[t0];
                t0++;
            }
            else {
                b[i].key = MAXKEY;
            }
            break;
        case 1:
            if (t1 < 3) {
                b[i].key = a1[t1];
                t1++;
            }
            else {
                b[i].key = MAXKEY;
            }
            break;
        case 2:
            if (t2 < 3) {
                b[i].key = a2[t2];
                t2++;
            }
            else {
                b[i].key = MAXKEY;
            }
            break;
        case 3:
            if (t3 < 3) {
                b[i].key = a3[t3];
                t3++;
            }
            else {
                b[i].key = MAXKEY;
            }
            break;
        case 4:
            if (t4 < 3) {
                b[i].key = a4[t4];
                t4++;
            }
            else {
                b[i].key = MAXKEY;
            }
            break;
        default:
            break;
        }
    }
    //败者树的建立及内部归并
    void K_Merge(LoserTree ls) {
        //模拟从外存中的5个初始归并段中向内存调取数据
        for (int i = 0; i <= k; i++) {
            input(i);
        }
        //创建败者树
        CreateLoserTree(ls);
        //最终的胜者存储在 is[0]中,当其值为 MAXKEY时,证明5个临时文件归并结束
        while (b[ls[0]].key != MAXKEY) {
            //输出过程模拟向外存写的操作
            printf("%d ", b[ls[0]].key);
            //继续读入后续的记录
            input(ls[0]);
            //根据新读入的记录的关键字的值,重新调整败者树,找出最终的胜者
            Adjust(ls, ls[0]);
        }
    }
    int main(int argc, const char * argv[]) {
        LoserTree ls;
        K_Merge(ls);
        return 0;
    }
  • 相关阅读:
    IIS Express 配置缓存位置
    Docker Demo on Docker
    前端的哪些坑
    如何在container中编译dotnet的eShopOnContainers
    JQuery 常用的那些东西
    jQuery选择器大全
    Js 跨域CORS报错 Response for preflight has invalid HTTP status code 405
    WPF 通过透明度遮罩和变换制作倒影效果
    Ons 让人欲哭无泪问题,官方介绍不详
    如何转换任何配置文件 文件中的内容
  • 原文地址:https://www.cnblogs.com/beixiaobei/p/10914216.html
Copyright © 2020-2023  润新知