數據結構與算法——競賽樹

1 概述

  • 競賽樹分爲贏者樹和輸者樹,贏者樹更直觀,輸者樹實現更高效。
  • 比賽用二叉樹來描述,每個外部節點表示一名選手,每個內部節點表示一場比賽,同一層內部節點代表一輪比賽,可以同時進行。
    在這裏插入圖片描述
    如果競賽樹是完全二叉樹,則對於n個選手的比賽,最少的比賽場次爲log2nlog_2n
  • 競賽樹不全是完全二叉樹,但是完全二叉樹可以是比賽的次數最少,競賽樹也成爲選擇樹。

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+offset)/2ilowExt(ilowExt+n1)/2i&gt;lowExt 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.
其中,s=2log2(n1)s=2^{|log_2(n-1)|}offset=2s1offset=2*s-1
(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 總結

最先適配法求解箱子問題
相鄰適配法求解箱子裝載問題

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章