笔记:败者树

//败者树示例与解析,败者树即是多个数据从二叉树的叶子节点出发,
//逐次比较,败者滞留子结点,胜者上升父节点,最后最终ls【0】为最终胜者。也可以说是多路归并算法
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;

#define LEN 5//败者树容量,多路归并数目
#define MIN -1//所有数据的可能最小值

int ls[LEN+1];
//败者树,ls[0]存放胜者,其余存放败者,实际上用到的只有前面len个点,
//树建成后,每个顶点分别对应一路归并序列(链表)
int buf[LEN+1];
//存放多路归并的头元素值,多出来的一位放MIN,这一位用于建树时的比较

void adjust(int s,int *buf){
    //s会一直指向buf表中比较过程中的胜者(这里是较小值),
    //而败者(在buf的下标)则被记录在ls【t】节点
    int t=(s+LEN)/2;
    //目前s指向的节点的父节点为t;如当s为0时,0路数据是挂在下标为2的败者树节点下充当叶节点的;
    //当s为1或者2时,挂在下标为3的败者树节点下充当子节点。
    //由于len为5,所以败者树只有五个节点,拥有数据叶节点的败者树节点则有2,3,4
    while(t>0)
    {//如果父节点不是ls【0】,则继续比较上升
        if(buf[s]>buf[ls[t]]){//如果当前节点s不小于等于父节点,则败,滞留这一层
            //下面就是交换ls【t】和s的值
            ls[t]^=s;//交换ls[t]和s
            s^=ls[t];//s记录胜者
            ls[t]^=s;//父节点记录败者
        }
        t/=2;//得到s的上一个父节点,下一轮继续比较
    }
    ls[0]=s;//最终的胜者记录于ls[0]
}

void build(int *buf){
    buf[LEN]=MIN;//最后一位放MIN,用于建树比较
    for(int i=0;i<LEN+1;++i)
        ls[i]=LEN;//所有败者树初始化为MIN的下标,这样不会让数据的下标升到不符合它的高度
    for(int i=0;i<LEN;++i)//这里是建树,让数据的下标依次上升到相应的高度
        adjust(i,buf);
}

int main()
{
    //初始buf
    int tmp[5]={18,21,16,11,19};
    memcpy(buf,tmp,LEN*sizeof(int));
    build(buf);
    /*
    建树完成后:
    ls:败者树(注意这里0是1父节点,1是2和3的父节点,所以跟1比较完永远是最小的)
    3  2  0  1  4  5
    buf:数据存放
    18  21  16  11  19  -1
    */
    cout<<buf[ls[0]]<<endl;//输出11

    //取出11后,buf[3]=17
    int tmp1[5]={18,21,16,17,19};
    memcpy(buf,tmp1,LEN*sizeof(int));
    adjust(3,buf);
    cout<<buf[ls[0]]<<endl;//输出16

    return 0;
}

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值