异常类 myExceptions 同 数据结构C++(1)线性表——数组实现(arrayList) 。
抽象基类 win 定义在 winner.h 中:
1 #pragma once
2
3 template<class T>
4 class win
5 {
6 public:
7 virtual ~win() {}
8 virtual void initialize(T *thePlayer, int theNumberOfPlayers) = 0; //生成赢者树
9 virtual int winner() const = 0; //返回赢者
10 virtual void play(int thePLayerID, int thePLayer) = 0; //改变thePLayerID的成绩之后重赛
11 };
类 winnerTree 的定义在 winnerTree.h 中:
1 #pragma once
2 #include <cmath>
3 #include "winner.h"
4 #include "myExceptions.h"
5
6 template<typename T>
7 class winnerTree : public win<T>
8 {
9 public:
10 winnerTree(T *thePlayer, int theNumberOfPlayers)
11 {
12 Tree = NULL;
13 initialize(thePlayer, theNumberOfPlayers);
14 }
15 ~winnerTree() {
16 std::cout << "~winnerTree Tree = " << Tree << std::endl;
17 delete []Tree;
18 std::cout << "~winnerTree()2" << std::endl;
19 }
20 void initialize(T *players, int playerNum); //初始化,创建赢者树
21 int winner() const //最终的胜利者
22 { return Tree[1]; }
23 int winner(int i) const //第 i 场比赛的胜利者
24 { return (i < numberOfPlayers) ? Tree[i] : 0; }
25 void play(int thePLayerID, int thePLayer);
26 void output(std::ostream &out) const;
27 protected:
28 // int lowExt;
29 int TreeSize;
30 T *Tree; //赢者树
31 int numberOfPlayers; //参赛人数
32 T *player; //比赛原始数组
33 void rePlay(int compete, int left, int right);
34 };
35
36 template<typename T>
37 void winnerTree<T>::rePlay(int compete, int left, int right)
38 {
39 for (int i = compete; i > 0; i /= 2)
40 Tree[i] = Tree[2 * i] > Tree[2 * i + 1] ? Tree[2 * i] : Tree[2 * i + 1];
41 }
42
43 template<typename T>
44 void winnerTree<T>::initialize(T *players, int playerNum)
45 {
46 if (playerNum < 2)
47 throw illegalParameterValue("参赛人数这么点儿,赛个毛啊");
48 player = players;
49 numberOfPlayers = playerNum;
50 delete []Tree;
51 //playerNum = 5,log_2 = 3,n = 4,TreeSize = 16
52 int log_2 = log10(playerNum-1) / log10(2) + 1;
53 int n = pow(2, log_2) - 1; //最多赛 n 次
54 TreeSize = pow(2, log_2 + 1);
55 std::cout << "log_2 = " << log_2 << std::endl;
56 Tree = new T[TreeSize]; //树最多需要 TreeSize 这么多空间
57 int TmpNum = TreeSize / 2 - playerNum;
58 std::cout << "initialize Tree = " << Tree << std::endl;
59 for (int i = 1, j = 0; i <= TreeSize; i++)
60 {
61 std::cout << "Tree[" << i << "] = ";
62 if (i < pow(2, log_2)) //先给内部结点填0
63 {
64 Tree[i] = 0;
65 std::cout << Tree[i] << std::endl;
66 }
67 else
68 {
69 if (i >= TreeSize - TmpNum * 2) //单人的对手也填0
70 {
71 if (i % 2)
72 Tree[i] = 0;
73 else
74 Tree[i] = players[j++];
75 }
76 else
77 Tree[i] = players[j++];
78 std::cout << Tree[i] << std::endl;
79 }
80 }
81 for (int j = n; j >= 1; j--)
82 {
83 Tree[j] = Tree[2 * j] > Tree[2 * j + 1] ? Tree[2 * j] : Tree[2 * j + 1];
84 }
85 }
86
87 template<typename T>
88 void winnerTree<T>::play(int thePLayerID, int thePLayer)
89 {
90 if (thePLayerID > numberOfPlayers)
91 throw illegalParameterValue("输入数据太大了!");
92 player[thePLayerID - 1] = thePLayer;
93 Tree[thePLayerID + numberOfPlayers] = thePLayer;
94 int n = (thePLayerID + numberOfPlayers) / 2;
95 rePlay(n, n * 2, n * 2 + 1);
96 }
97
98 template<typename T>
99 void winnerTree<T>::output(std::ostream &out) const
100 {
101 for (int i = 1; i < TreeSize; i++)
102 out << Tree[i] << " ";
103 out << std::endl;
104 }
参考文献:
[1].Sartaj Sahni. 数据结构、算法与应用[M]. 机械工业出版社, 2000.