loserTree实现多路合并

// k 路归并时间复杂度为 O(log2^m / log2^k * (k-1) * (n-1)) n为
// 对n个外部文件进行外排,m为归并断个数     (k- 1) / log 2^k 随k的增长而增长
// 因此内部采用 loser tree进行排序
// 为什么不采用胜者树
// 败者树是一个完全二叉树,非叶子节点记录失败者。那么相对于胜者树,具有访存小的优势。胜者树胜者拿走后,
// 整条通路(从叶子到根)所有记录的胜者信息失效,那么新加入节点需要从叶子一直遍历到根,有可能每次都要
// 写入(更新新的胜者)。而败者树,新加入的节点可以利用整条路径的败者信息。

// 多路 merage 的实现 (只是简单把merage实现了,要排序还得递归再排)
#include<bits/stdc++.h>
#define rep(i, n) for(int i=0;i!=n;++i)
#define per(i, n) for(int i=n-1;i>=0;--i)
#define Rep(i, sta, n) for(int i=sta;i!=n;++i)
#define rep1(i, n) for(int i=1;i<=n;++i)
#define per1(i, n) for(int i=n;i>=1;--i)
#define Rep1(i, sta, n) for(int i=sta;i<=n;++i)
#define L rt<<1
#define R rt<<1|1
#define inf (0x3f3f3f3f)
#define llinf (1e18)
#define ALL(A) A.begin(),A.end()
#define SIZE(A) ((int)A.size())
#define MOD (1e9 + 7)
#define PII pair<int,int>
#define LEN 32
typedef long long i64;
using namespace std;
struct Array{
	vector<int> arr;
	int pos;
}*Arr;
int k,Count;//k路进行merage
int *LoserTree, *External;
void adjust(int cur)
{
	int p = (cur + k) >> 1; // 当前节点的父节点
	while(p > 0){
		if(External[cur] > External[LoserTree[p]])
			swap(cur,LoserTree[p]);//交换 小的值上浮比较,大的修改为父节点
		p >>= 1;
	}//cur 一定为最小的那个下标 放入缓存
	LoserTree[0] = cur;
}
void CreateLoserTree()//创建败者树
{
	rep(i,k) LoserTree[i] = i;
	per(i,k)	adjust(i);//调整每一个节点,构建败者树
}
void k_Merage()
{
	rep(i,k){
		int pos = Arr[i].pos;
		External[i] = Arr[i].arr[pos];//初始化数据块
		++Arr[i].pos;
	}
	CreateLoserTree();
	int index = 0;
	while(index < Count){
		int minIndex = LoserTree[0];// minIndex 为最小的归并的列
		cout << External[minIndex] << " ";
		++index;
		if(Arr[minIndex].pos >= Arr[minIndex].arr.size())
			External[minIndex] = inf;//对应的归并的列已经全部归并
		else{
			External[minIndex] = Arr[minIndex].arr[Arr[minIndex].pos];
			++Arr[minIndex].pos;
		}
		adjust(minIndex);//调整对应的排列
	}
}
int main() {
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
	int num,val;	cin >> k;
	Arr = new Array[k];
	rep(i,k){
		cin >> num;
		Count += num;
		rep(j,num){
			cin >> val;
			Arr[i].arr.push_back(val);
		}
		Arr[i].pos = 0;
	}
	LoserTree = new int[k];
	External = new int [k];

	k_Merage();
	return 0;
}

  

posted on 2020-09-11 22:31  chengyulala  阅读(332)  评论(0编辑  收藏  举报

导航