败者树

//利用败者树求:
//20个一维数组,每个数组有500个元素,为叶子节点提供数据。本题中仅给出了测试用的
//40个元素,例程中输出最大的前10个元素
#include<iostream>
#include<vector>
using namespace std;


const int branchesLength=20;      //共有20路数组
int branches[branchesLength][500]=
{
{1000,90},{999,888},{1001,990},{887,877},{987,978},
{1001,901},{992,883},{1005,992},{887,877},{987,978},
{1002,902},{993,884},{1007,991},{887,877},{987,978},
{1003,903},{994,882},{989,900},{887,877},{987,978}
};


//败者树的非叶子节点,记录数据源的索引位置,根据节点的值可以定位到所指向的数据源
int tree[branchesLength];


//败者树的叶子节点,叶子节点与数据源是一一对应的,即第一个叶子节点记录第一个数据源的当前数据
//编号都是从0开始
int nodes[branchesLength];


//nodes_iterator[i]记录第i路数组当前已取到第几个元素(从0开始)
int nodes_iterator[branchesLength]={0};


//设置第index个叶子节点的下一个数据
void put(int index)
{
    nodes[index]=branches[index][nodes_iterator[index]++];
}


//获取第index叶子节点的当前数据
int get(int index)
{
    return nodes[index];
}


//调整第index个叶子节点,具体调整过程为:叶子节点和父节点比较,败者留着父节点的位置,
//胜者继续和父节点的父节点比较,直到树的根节点
//核心函数
void adjust(int index)
{
    int size=branchesLength;
    int t=(size+index)/2;
    while(t>0)
    {
        if(get(tree[t])>get(index))
        {
            int temp=tree[t];
            tree[t]=index;
            index=temp;
        }
        t/=2;
    }
    tree[0]=index;    //此轮胜者
}


//依次读取数据源中的数据进行归并排序,返回排序后的数据列表
vector<int> Merge()
{
    vector<int> list1;
    int top;
    int i=0;
    while(i<10)
    {
        top=nodes[tree[0]];
        list1.push_back(top);
        cout<<top<<" ";
        i++;
        put(tree[0]);
        adjust(tree[0]);
    }
    return list1;
}


//初始化构建败者树
void init()
{
    int size=branchesLength;
    for(int i=0;i<size;i++)
        put(i);
    int winner=0;
    for(int i=1;i<size;i++)
    {
        if(get(i)>get(winner))
            winner=i;
    }
    for(int i=0;i<branchesLength;i++)  //非叶子节点初始化为冠军节点
        tree[i]=winner;
    for(int i=size-1;i>=0;i--)   //从后向前依次调整非叶子节点
        adjust(i);
}


int main()
{
    init();
    Merge();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值