Data Structures, Algorithms, & Applications in Java
Chapter 14, Exercise 19
The data members of the new class are the same as those for the
class CompleteWinnerTree of the text.
To initialize a loser tree, we use the strategy described in Exercise 14.17 (b).
We first set tree[i]
for the nodes that lie between the players and the match nodes.
Next, we play the matches at tree[i]
for i = n-1, n-2, ..., 1, in that order and record the
winners of these matches.
Finally, we examine the match nodes in the order
1, 2, ... n-1 and replace the winners by the losers.
To replay matches when the overall winner changes, we
play matches on the path from the grandparent of this winner to the root
of the loser tree.
The code for the new implementation is given below.
public class CompleteLoserTree2
{
// data members
int lowExt; // lowest-level external nodes
int offset; // 2^log(n-1) - 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[0];}
/** initialize loser 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");
player = thePlayer;
tree = new int [2 * n];
// compute s = 2^log (n-1)
int s;
for (s = 1; 2 * s <= n - 1; s += s);
lowExt = 2 * (n - s);
offset = 2 * s - 1;
// initialize nodes that lie between players and match nodes
for (int i = 1; i <= lowExt; i ++)
tree[i + offset] = i;
for (int i = lowExt + 1; i <= n; i++)
tree[i - lowExt + n - 1] = i;
// play matches
for (int i = n - 1; i >= 1; i--)
tree[i] = player[tree[2 * i]].winnerOf(player[tree[2 * i + 1]]) ?
tree[2 * i] : tree[2 * i + 1];
tree[0] = tree[1]; // overall winner
// replace winners by losers
for (int i = 1; i < n; i++)
tree[i] = (tree[i] == tree[2 * i]) ? tree[2 * i + 1] : tree[2 * i];
}
/** replay matches for previous winner */
public void rePlay()
{
if (player == null)
throw new IllegalArgumentException
("tree must be initialized first");
// set p to first match node
int p;
if (tree[0] <= lowExt)
p = (tree[0] + offset) / 2;
else
p = (tree[0] - lowExt + player.length - 2) / 2;
// play matches from p to root
int currentWinner = tree[0];
for (; p >= 1; p /= 2)
if (player[tree[p]].winnerOf(player[currentWinner]))
{// currentWinner loses the match at this node
int temp = tree[p];
tree[p] = currentWinner;
currentWinner = temp;
}
tree[0] = currentWinner; // overall winner
}
}
A test program and sample input and output are given in the files
CompleteLoserTree2.*