败者树 java_败者树的java实现

本文介绍了败者树的概念,这是一种能快速找到k个记录中最小值的数据结构,常用于多路归并排序。败者树通过Java代码实现,包括初始化、删除、添加元素和获取最小值的方法,能够有效减少IO次数并保持内部归并效率。
摘要由CSDN通过智能技术生成

记录败者,胜者参加下一轮比赛,当新的元素到达的时候,log2(K)调整就可以选出胜者,下面的log2(K)代进1式,就可以抵消掉k的影响,从而与k无关,那么我们就可以,通过增大k,减少IO次数,并且不会降低内部归并的效率。

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

算法实现

1、一共k路,b[i]对应第i路,比如一共5路 b[0],b[1],b[2],b[3],b[4]对应5路的首元素

2、ls[i],是一棵败者树ls[0],ls[1],ls[2],ls[3],ls[4],分别存储上面的b[i]的下标i,这样就利用元素的下标,组织了成它们的树关系

初始化时,ls[i]=i;

然后从最后一个结点开始调整,t=(s+k)/2表示的是s的父结点, 然后逐渐向上向父结点比较t=t/2,最后到达ls[0],它是冠军,经过所有的结点调整,就成了一棵败者树,最后输出b[ls[0]],

k路合并,根据ls[0],可以知道是从哪路输出,然后再从哪路输入

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

败者树在数据结构的课本上就有,它可以直接获得k个记录中的最小值/最大值,并且调整的时间复杂度为log(k),因此可以在多路归并排序中用来加速多个多并段中最小值/最大值的查找,从而提高归并的速度。

败者树的Java代码如下,其中的Result是待排记录的抽象:

/*

* ResultSet.java 0.0.1 2013/04/04

* Copyright(C) 2013 db-iir RUC. All rights reserved.

*/

import java.util.ArrayList;

/**

* This Class implements the loser tree algorithm.

*

* @version 0.0.1, 2013/04/04

*/

public class LoserTree

{

private int[] tree = null;// 以顺序存储方式保存所有非叶子结点

private int size = 0;

private ArrayList leaves = null;// 叶子节点

public LoserTree(ArrayList initResults)

{

this.leaves = initResults;

this.size = initResults.size();

this.tree = new int[size];

for (int i = 0; i < size; ++i)

{

tree[i] = -1;

}

for (int i = size - 1; i >= 0; --i)

{

adjust(i);

}

}

public void del(int s)

{

leaves.remove(s);

size--;

tree = new int[size];

for (int i = 0; i < size; ++i)

{

tree[i] = -1;

}

for (int i = size - 1; i >= 0; --i)

{

adjust(i);

}

}

public void add(Result leaf, int s)

{

leaves.set(s, leaf);// 调整叶子结点

adjust(s);// 调整非叶子结点

}

public Result getLeaf(int i)

{

return leaves.get(i);

}

public int getWinner()

{

return tree[0];

}

private void adjust(int s)

{

// s指向当前的值最小的叶子结点(胜者)

int t = (s + size) / 2;// t是s的双亲

while (t > 0)

{

if (s >= 0

&& (tree[t] == -1 || leaves.get(s).compareTo(

leaves.get(tree[t])) > 0))

{

// 将树中的当前结点指向其子树中值最小的叶子

int tmp = s;

s = tree[t];

tree[t] = tmp;

}

t /= 2;

}

tree[0] = s;// 树根指向胜者

}

} 在产生初始归并段时,使用ArrayList和Collections.sort()就可以了,这个是一种改进的归并内部排序算法,我试验过,效率很高的,给13个100万条的字符串列表(每个字符串约10个字符、有重复)排序,在四核3.2GhzCPU的机器上、单线程也只用了十秒钟而已。其实外排很大一部分的时间消耗在IO上,特别是对于CPU性能好的工作站、服务器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值