collection2  v0.6.0
Loading...
Searching...
No Matches
tree.hpp
1//
2// ツリー
3//
4
5#ifndef COLLECTION2_TREE_H
6#define COLLECTION2_TREE_H
7
8#include <stddef.h>
9#include <stdint.h>
10
11#include "common.hpp"
12
13namespace collection2 {
14
21template <typename Element, typename Size = size_t>
22struct TreeNode {
23 // 有効なノードか
24 bool isEnabled = false;
25
26 // 左側子ノードへのポインタ
27 TreeNode* lhs = nullptr;
28
29 // 右側子ノードへのポインタ
30 TreeNode* rhs = nullptr;
31
32 // ノードが持つ要素
33 Element element;
34
40 bool isLeaf() const {
41 return (lhs == nullptr) && (rhs == nullptr);
42 };
43};
44
48enum class TreeNodeSide : uint8_t {
50 Left,
51
53 Right
54};
55
62template <typename Element, typename Size = size_t>
63class Tree {
64 private:
68 TreeNode<Element>* const internalData;
69
73 Size internalDataSize;
74
75 public:
82 Tree(TreeNode<Element, Size>* const data, const Size& dataSize);
83
84 Tree(const Tree&) = delete;
85 Tree& operator=(const Tree&) = delete;
86
87 ~Tree() = default;
88
94
102
109 TreeNode<Element, Size>* retainNode(const Element& element) const;
110
124 const Element& target,
125 const TreeNodeSide side,
126 TreeNode<Element, Size>** addedNodePtr = nullptr);
127
138 const TreeNodeSide side) const;
139
148
154 Size capacity() const {
155 return internalDataSize;
156 }
157};
158
159template <typename Element, typename Size>
160Tree<Element, Size>::Tree(TreeNode<Element, Size>* const data, const Size& dataSize)
161 : internalData(data), internalDataSize(dataSize) {
163};
164
165template <typename Element, typename Size>
167 for (Size i = 0; i < internalDataSize; i++) {
168 internalData[i].isEnabled = false;
169 }
170}
171
172template <typename Element, typename Size>
174 for (Size i = 0; i < internalDataSize; i++) {
175 if (internalData[i].isEnabled) {
176 continue;
177 }
178
179 // 見つかったらノードを初期化して返す
180 internalData[i].isEnabled = true;
181 internalData[i].lhs = nullptr;
182 internalData[i].rhs = nullptr;
183 return &(internalData[i]);
184 }
185 return nullptr;
186}
187
188template <typename Element, typename Size>
190 // ノードを確保
191 auto* node = retainNode();
192 if (node == nullptr) {
193 return nullptr;
194 }
195
196 // 値を設定して返す
197 node->element = element;
198 return node;
199}
200
201template <typename Element, typename Size>
204 const Element& target,
205 const TreeNodeSide side,
206 TreeNode<Element, Size>** addedNodePtr) {
207 // 親ノードがnullであってはならない(単純なノードの確保はretainNodeを使う)
208 if (parent == nullptr) {
209 return OperationResult::Empty;
210 }
211
212 // 新しいノードをもらってくる
213 auto* newNode = retainNode();
214 if (newNode == nullptr) {
215 if (addedNodePtr != nullptr) {
216 *addedNodePtr = nullptr;
217 }
218 return OperationResult::Overflow;
219 }
220
221 // 値をセット
222 newNode->element = target;
223
224 // 新規生成したノードへのポインタを渡す
225 if (addedNodePtr != nullptr) {
226 *addedNodePtr = newNode;
227 }
228
229 // 親ノードの追加したい方に追加するノードを接続する
230 return linkNode(*parent, newNode, side);
231}
232
233template <typename Element, typename Size>
235 if (node == nullptr) {
236 return OperationResult::Empty;
237 }
238
239 // sideで指定された方にnodeを繋ぐ すでにある場合は書き換えない
240 if (side == TreeNodeSide::Left) {
241 if (parent.lhs != nullptr) {
242 return OperationResult::Overflow;
243 }
244 parent.lhs = node;
245 }
246 if (side == TreeNodeSide::Right) {
247 if (parent.rhs != nullptr) {
248 return OperationResult::Overflow;
249 }
250 parent.rhs = node;
251 }
252 return OperationResult::Success;
253}
254
255template <typename Element, typename Size>
257 // リーフならデアクティベートして終わり
258 if (target->isLeaf()) {
259 target->isEnabled = false;
260 return;
261 }
262
263 // そうでなければ再帰的に削除
264 if (target->lhs != nullptr) {
265 removeChild(target->lhs);
266 target->lhs = nullptr;
267 }
268 if (target->rhs != nullptr) {
269 removeChild(target->rhs);
270 target->rhs = nullptr;
271 }
272}
273
274} // namespace collection2
275
276#endif
ツリー
Definition: tree.hpp:63
void initializeTreeNodePool()
ツリーノードプールを初期化する
Definition: tree.hpp:166
OperationResult appendChild(TreeNode< Element, Size > *parent, const Element &target, const TreeNodeSide side, TreeNode< Element, Size > **addedNodePtr=nullptr)
子ノードを生成し、既存ノードに追加する
Definition: tree.hpp:202
void removeChild(TreeNode< Element, Size > *target)
子ノードを削除する
Definition: tree.hpp:256
TreeNode< Element, Size > * retainNode() const
内部ノードプールから空きノードを探し、確保する
Definition: tree.hpp:173
Size capacity() const
ツリーが持てるノードおよびリーフの全体長を返す
Definition: tree.hpp:154
Tree(TreeNode< Element, Size > *const data, const Size &dataSize)
内部データを扱う領域とそのサイズを指定してリストを初期化
Definition: tree.hpp:160
OperationResult linkNode(TreeNode< Element, Size > &parent, TreeNode< Element, Size > *node, const TreeNodeSide side) const
ノードを別のノードに接続する
Definition: tree.hpp:234
OperationResult
コレクション操作結果
Definition: common.hpp:14
ツリーの各ノードを表す構造体
Definition: tree.hpp:22
bool isLeaf() const
リーフかどうかを調べる
Definition: tree.hpp:40