数据结构与算法——竞赛树

1 概述

  • 竞赛树分为赢者树和输者树,赢者树更直观,输者树实现更高效。
  • 比赛用二叉树来描述,每个外部节点表示一名选手,每个内部节点表示一场比赛,同一层内部节点代表一轮比赛,可以同时进行。
    在这里插入图片描述
    如果竞赛树是完全二叉树,则对于n个选手的比赛,最少的比赛场次为 l o g 2 n log_2n log2n
  • 竞赛树不全是完全二叉树,但是完全二叉树可以是比赛的次数最少,竞赛树也成为选择树。

2 赢者树

2.1 定义
(1)赢者树:有n个选手的赢者树是一个完全二叉树,有n个外部节点和n-1个内部节点,每个内部节点记录的是该节点比赛的赢者。
分类:最大赢者树、最小赢者树(平局的时候左孩子选手获胜)
优点:当一个选手分数改变时,修改竞赛树比较容易。
2.2 抽象数据类型winnerTree
假设:选手个数一定,初始化后不能增减选手。

选手本身并不是赢者树的组成部分,内部节点才是。

在这里插入图片描述

template<class T>
class winnerTree
{
public:
	virtual ~winnerTree() {}
	virtual void initialize(T* thePlayer, int theNumberOfPlayers) = 0;
	// create winner tree with thePlayer[1:numberOfPlayers]
	virtual int winner() const = 0;
	// return index of winner
	virtual void rePlay(int thePLayer) = 0;
	// replay matches following a change in thePLayer
};

2.3 赢者树的实现
(1)表示
在这里插入图片描述
n名选手,n-1个内部节点分别对应数组player[1: n],tree[1: n-1]
对于任何一个外部节点player[i],其父节点tree[p]由以下公式给出:
p = { ( i + o f f s e t ) / 2 i ≤ l o w E x t ( i − l o w E x t + n − 1 ) / 2 i &gt; l o w E x t p=\left\{ \begin{aligned} (i+offset)/2 &amp;&amp;&amp;&amp;&amp;&amp; {i\leq lowExt } \\ (i-lowExt+n-1)/2 &amp;&amp;&amp;&amp;&amp;&amp; {i &gt;lowExt} \end{aligned} \right. p={(i+offset)/2(ilowExt+n1)/2ilowExti>lowExt
其中, s = 2 ∣ l o g 2 ( n − 1 ) ∣ s=2^{|log_2(n-1)|} s=2log2(n1) o f f s e t = 2 ∗ s − 1 offset=2*s-1 offset=2s1
(2)初始化
从右孩子开始,逐层往上,且每层从左往右依次考察右孩子选手。
(3)类completeWinnerTree

template<class T>
class completeWinnerTree : public winnerTree<T>
{
public:
	completeWinnerTree(T* thePlayer, int theNumberOfPlayers)
	{
		tree = NULL;
		initialize(thePlayer, theNumberOfPlayers);
	}
	~completeWinnerTree() { delete[] tree; }
	void initialize(T*, int);
	int winner() const
	{
		return tree[1];
	}
	int winner(int i) const
	{
		return (i < numberOfPlayers) ? tree[i] : 0;
	}
	// return winner of match at node i
	void rePlay(int);
	void output() const;
private:
	int lowExt;           // lowest-level external nodes
	int offset;           // 2^log(n-1) - 1
	int* tree;            // array for winner tree
	int numberOfPlayers;
	T* player;            // array of players
	void play(int, int, int);
};

3 总结

最先适配法求解箱子问题
相邻适配法求解箱子装载问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值