对于对路归并与败者树的概念参见
https://www.cnblogs.com/charlesblc/p/6138908.html
下面模拟了简单的利用败者树进行多路归并的场景
#include <iostream>
#include <vector>
#include <time.h>
#include <algorithm>
using namespace std;
//5路归并树
const int K = 5;
//最小关键字
const int MINKEY = -0x3f3f3f3f;
//最大关键字
const int MAXKEY = -MINKEY;
//表示关键字的范围
void Adjust(vector<int> &b,vector<int> &ls, int s)
{
//调整loser树
int t = (s + K)/2;
while (t > 0)
{
if(b[s] > b[ls[t]])
{
//交换ls[t] 与 s 的值
ls[t] = s ^ ls[t];
s = s ^ ls[t];
ls[t] = s ^ ls[t];
}
t /= 2;
}
ls[0] = s;
}
void CreatLoserTree(vector<int> &b,vector<int> &ls)
{
b[K] = MINKEY;
//创建失败树
for(int i = 0; i < ls.size(); i++)
{
ls[i] = K;
}
for(int i = K-1; i >= 0; i--)
{
//调整每一个
Adjust(b,ls,i);
}
}
//多路归并与失败树
int main()
{
srand((unsigned int)time(NULL));
vector<vector<int> > vec;
vector<int> ls; //失败树
vector<int> b;
//存放K个关键字
b.resize(K+1);
ls.resize(K);
//记录总的元素的个数
int count = 0;
for(int i = 0; i < K; i++)
{
vector<int> tmp;
for(int j = 0; j < 20; j++)
{
count++;
tmp.push_back(rand() % 100);
}
//排序
sort(tmp.begin(),tmp.end(),greater<int>());
vec.push_back(tmp);
tmp.clear();
}
//初始化b数组,loser树中的数据项
for(int i = 0; i < K; i++)
{
b[i] = vec[i].back();
vec[i].pop_back();
}
//创建loser树
CreatLoserTree(b,ls);
vector<int> res; //归并后的结果
//取归并后的结果
while(count > 0)
{
res.push_back(b[ls[0]]);
count--;
if(vec[ls[0]].size() == 0)
{
//如果一个序列变为空,则将该序列对应的loser树的位置置为最大值
b[ls[0]] = MAXKEY;
}
else
{
//如果序列不为空,即该序列的还没有归并完,则从序列中取出一个最小值
//加入到loser树中
b[ls[0]] = vec[ls[0]].back();
vec[ls[0]].pop_back();
}
Adjust(b,ls,ls[0]);
}
for(auto val:res)
{
cout << val << " ";
}
cout << endl;
return 0;
}