#ifndef CHAPTER13_WINNERTREE_H
#define CHAPTER13_WINNERTREE_H
template<class T>
class winnerTree
{
public:
virtual ~winnerTree()= default;
virtual void initialize(T *thepalyer, int theNumberOfPlayers) = 0;
[[nodiscard]] virtual int winner() const = 0;
virtual void rePlay(int thePlayer, T newElement) = 0;
};
#endif
#ifndef CHAPTER13_COMPLETEWINNERTREE_H
#define CHAPTER13_COMPLETEWINNERTREE_H
#include "winnerTree.h"
#include <cmath>
#include "iostream"
#include "vector"
template<class T>
class completeWinnerTree : public winnerTree<T>
{
public:
~completeWinnerTree() = default;
completeWinnerTree()= default;
void initialize(T *thePlayer, int theNumberOfPlayers);
[[nodiscard]] int winner() const;
void rePlay(int thePlayer, T newElement);
void getSort(int* &mySort);
void initWithRecursion(T *thePlayers, int theNumberOfPlayers);
private:
int Recursion(int leftNode, int RightNode);
int *tree{};
T *Player;
int s{};
int lowInnerExt{};
int lowOuterExt{};
int offset{};
int NumberOfPlayers{};
};
template<class T>
void completeWinnerTree<T>::initialize(T *thePlayers, int theNumberOfPlayers) {
tree = new int[theNumberOfPlayers];
NumberOfPlayers = theNumberOfPlayers;
s = 1 << int(log2(theNumberOfPlayers - 1));
lowInnerExt = (theNumberOfPlayers - s);
lowOuterExt = 2 * lowInnerExt;
offset = 2 * s - 1;
Player = new T[theNumberOfPlayers + 1];
std::copy(thePlayers, thePlayers + theNumberOfPlayers + 1, Player);
for (int i = 2; i <= theNumberOfPlayers;) {
int currentId = i;
int pTree = 0;
if (i <= lowOuterExt){
pTree = (i+offset)/2;
if (i < lowOuterExt || lowInnerExt%2==0)
i += 2;
else
++i;
} else{
pTree = (i - lowOuterExt + theNumberOfPlayers - 1) / 2;
i += 2;
}
if (currentId == lowOuterExt+1){
tree[pTree] = thePlayers[currentId] < thePlayers[tree[(lowOuterExt+offset)/2]] ? currentId : tree[(lowOuterExt+offset)/2];
} else
tree[pTree] = thePlayers[currentId] < thePlayers[currentId-1] ? currentId : currentId-1;
while (pTree%2 && pTree!=1) {
tree[pTree/2] = thePlayers[tree[pTree]] < thePlayers[tree[pTree - 1]] ? tree[pTree] : tree[pTree-1];
pTree /= 2;
}
}
}
template<class T>
int completeWinnerTree<T>::winner() const {
return tree[1];
}
template<class T>
void completeWinnerTree<T>::rePlay(int thePlayer, T newElement) {
Player[thePlayer] = newElement;
int pTree = 0;
if (thePlayer <= lowOuterExt)
pTree = (thePlayer+offset)/2;
else
pTree = (thePlayer - lowOuterExt + NumberOfPlayers - 1) / 2;
if (tree[pTree] != thePlayer && Player[tree[pTree]] < thePlayer)
return;
else{
int anotherPlayer;
if (lowInnerExt%2!=0 && thePlayer == lowOuterExt + 1)
anotherPlayer = tree[(lowOuterExt+offset)/2];
else{
if(thePlayer%2==0)
anotherPlayer = thePlayer - 1;
else
anotherPlayer = thePlayer + 1;
}
tree[pTree] = Player[thePlayer] < Player[anotherPlayer] ? thePlayer : anotherPlayer;
while (pTree!=1) {
if (pTree%2) {
tree[pTree / 2] = Player[tree[pTree]] < Player[tree[pTree-1]] ? tree[pTree] : tree[pTree-1];
pTree /= 2;
} else {
if (pTree == NumberOfPlayers - 1)
tree[pTree / 2] = Player[tree[pTree]] < Player[lowOuterExt + 1] ? tree[pTree] : lowOuterExt + 1;
else
tree[pTree / 2] = Player[tree[pTree]] < Player[tree[pTree + 1]] ? tree[pTree] : tree[pTree + 1];
pTree /= 2;
}
}
}
}
template<class T>
void completeWinnerTree<T>::getSort(int *&mySort) {
mySort = new int[sizeof(Player)];
T *backUp = new T[sizeof(Player)];
std::copy(Player, Player + sizeof(Player), backUp);
for (int i = 1; i <= NumberOfPlayers; ++i) {
int num = winner();
mySort[i] = num;
Player[num] = INT16_MAX;
rePlay(num, INT16_MAX);
}
initialize(backUp, sizeof(backUp));
}
template<class T>
void completeWinnerTree<T>::initWithRecursion(T *thePlayers, int theNumberOfPlayers) {
tree = new int[theNumberOfPlayers];
NumberOfPlayers = theNumberOfPlayers;
s = 1 << int(log2(theNumberOfPlayers - 1));
lowInnerExt = (theNumberOfPlayers - s);
lowOuterExt = 2 * lowInnerExt;
offset = 2 * s - 1;
Player = new T[theNumberOfPlayers + 1];
std::copy(thePlayers, thePlayers + theNumberOfPlayers + 1, Player);
tree[1] = Recursion(2, 3);
for (int i = 1; i < theNumberOfPlayers; ++i) {
std::cout << tree[i] << " ";
}
}
template<class T>
int completeWinnerTree<T>::Recursion(int leftNode, int rightNode) {
int left, right;
if (leftNode < NumberOfPlayers)
left = tree[leftNode] = Recursion(2 * leftNode, 2 * leftNode + 1);
else if (leftNode > NumberOfPlayers-1 && leftNode < 2 * s)
left = leftNode-(NumberOfPlayers-1)+lowOuterExt;
else
left = ((leftNode/2)-s)*2+1;
if (rightNode < NumberOfPlayers)
right = tree[rightNode] = Recursion(2 * rightNode, 2 * rightNode + 1);
else if (rightNode > NumberOfPlayers-1 && rightNode < 2 * s)
right = rightNode-(NumberOfPlayers-1)+lowOuterExt;
else
right = left+1;
return Player[left] < Player[right] ? left : right;
}
#endif
#include <iostream>
#include "include/completeWinnerTree.h"
using namespace std;
int main() {
completeWinnerTree<int> tree;
int player[] = {0, 12, 34, 8, 20, 9, 3, 55};
tree.initWithRecursion(player, 7);
cout << endl << tree.winner() << endl;
int *mySort;
tree.getSort(mySort);
for (int i = 1; i < sizeof(mySort); ++i) {
cout << mySort[i] << " ";
}
cout << endl << tree.winner() << endl;
return 0;
}