The new implementation is given below. The data member
offset equals m-1.
Since the players and internal nodes
are in different arrays, it is still necessary to play
lowest-level matches separately from the remaining matches.
public class FullWinnerTree implements WinnerTree
{
// data members
int offset; // 2^ceil(log n) - 1
int [] tree; // array for winner tree
Playable [] player; // array of players
// only default constructor available
/** @return the winner of the tournament
* @return 0 if there are no players */
public int getWinner()
{return (tree == null) ? 0 : tree[1];}
/** initialize winner tree for thePlayer[1:thePlayer.length-1] */
public void initialize(Playable [] thePlayer)
{
int n = thePlayer.length - 1;
if (n < 2)
throw new IllegalArgumentException
("must have at least 2 players");
// compute smallest m >= n and a power of 2
int m;
for (m = 1; m < n; m += m);
// set instance data members
player = thePlayer;
tree = new int [m];
offset = m - 1;
int p = (n + offset) / 2; // tree[p] is largest p where a match is played
// play match at tree[p]
if (n % 2 == 1)
// n is odd, tree[p] has only one child
tree[p] = n;
else
// n is even, tree[p] has two children
tree[p] = player[n - 1].winnerOf(player[n]) ? n - 1 : n;
// play remaining matches at lowest level
int lp = 1; // player[lp] is left child player
for (int i = m / 2; i < p; i++)
{
tree[i] = player[lp].winnerOf(player[lp + 1]) ? lp : lp + 1;
lp += 2;
}
// play matches at remaining levels
for (int i = p / 2; i >= 1; i--)
{
int lc = 2 * i; // index of left child of node i
if (tree[lc + 1] == 0)
// no right child
tree[i] = tree[lc];
else
tree[i] = player[tree[lc]].winnerOf(player[tree[lc + 1]]) ?
tree[lc] : tree[lc + 1];
}
}
/** replay matches for player i */
public void rePlay(int i)
{
int n = player.length - 1; // number of players
if (i <= 0 || i > n)
throw new IllegalArgumentException("No player " + i);
// play first match
int p = (i + offset) / 2; // node for first match
if (2 * p + 1 > n)
// only player for this match
tree[p] = i;
else
{// two players
int lp = 2 * p - offset; // left player
tree[p] = player[lp].winnerOf(player[lp + 1]) ? lp : lp + 1;
}
// play remaining matches
p /= 2; // move to parent
for (; p >= 1; p /= 2)
if (tree[2 * p + 1] == 0)
// only one player
tree[p] = tree[2 * p];
else
// two players
tree[p] = player[tree[2 * p]].winnerOf(
player[tree[2 * p + 1]]) ? tree[2 * p] : tree[2 * p + 1];
}
}