Intrusive Containers
Loading...
Searching...
No Matches
TreeIn.h
Go to the documentation of this file.
1#ifndef TreeIn_H
2#define TreeIn_H
3
4/**
5@file TreeIn.h
6@brief Intrusive Binary Tree (unbalanced).
7
8This file defines a pair of templates (TreeInRoot and TreeInNode) that
9implement an intrusive binary tree.
10
11@copyright (c) 2014-2024 Richard Damon
12@parblock
13MIT License:
14
15Permission is hereby granted, free of charge, to any person obtaining a copy
16of this software and associated documentation files (the "Software"), to deal
17in the Software without restriction, including without limitation the rights
18to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19copies of the Software, and to permit persons to whom the Software is
20furnished to do so, subject to the following conditions:
21
22The above copyright notice and this permission notice shall be included in
23all copies or substantial portions of the Software.
24
25THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
31THE SOFTWARE.
32@endparblock
33
34@par Overview
35@parblock
36TreeInRoot and TreeInNode provide a simple API to allow classes to provide a
37basic Tree <-> Node relationship (1 Tree Root holding many Nodes) as a Binary Tree.
38
39Note that this class makes no attempt to "balance" the tree, but is designed that it can be derived
40from by a class to implement any needed balancing.
41
42To create this relationship, the class to act as the tree root derives from the template TreeInRoot,
43and the class to act as the Node from TreeInNode, both with a first parameter of the class name
44of the List class, a second parameter of the Node class, and a 3rd type parameter for the type for the
45Key to use in searching the tree. There is an optional integral 4rd parameter
46to allow the classes to inherent from these multiple times if you need to represent multiple simultaneous
47relationships. This inheritance should be public, or you need to add the TreeInRoot and TreeInNode templates as
48friends.
49
50At the point of declaration, both classes need to be declared, so you will typically have a forward of the other
51class before the definition of the class. At the point of usage of members, generally the full definition of both
52classes is needed to instance the code for the template.
53
54The user of the class will need to define two member functions to configure the tree.
55int TreeInRoot::compare(N& node1, N& node2) const;
56and
57int TreeInRoot::compare(N& node, K key) const;
58
59Inside this file, the following types have the following meanings:
60
61R: The "user" type that will be derived from TreeInRoot
62
63N: The "user" type that will be derived from TreeInNode
64
65K: The "user" type that represents the Key for the tree.
66
67n: The integer parameter for the template to allow multiple usage
68
69List: The particular instance of TreeInRoot<R, N, K, n> being used
70
71Node: The particular instance of TreeInNode<R, N, K, n> being used
72
73node: will have type N*, to be used when walking the list.
74@endparblock
75
76@invariant
77@parblock
78Given:
79+ R& root
80+ N& node
81
82TreeInRoot
83+ if root.m_base != nullptr:
84 + root.m_base-> m_root == &root
85 + root.m_base-> m_parent == nullptr
86
87TreeInNode
88+ if node.m_root == NULL: // Free Node
89 + node.m_parent == NULL
90 + node.m_left == NULL
91 + node.m_right == NULL
92+ if node.m_root != NULL and node.m_parent == NULL // Base Node
93 + node.m_root->m_base == &node
94+ if node.m_parent != nullptr: // Child Node
95 + Either node.m_parent->m_left or node.m_parent->m_right == &node
96+ if node.m_left != nullptr
97 + node.m_left->m_parent = &node
98 + node.m_left->m_root == node.m_root
99 + node.m_root->compare(node, *m_left) <= 0
100 + node.m_root->compare(*m_left, node) >= 0
101+ if node.m_right != nullptr:
102 + node.m_right->m_parent = &node
103 + node.m_right->m_root == node.m_root
104 + node.m_root->compare(node, *m_right) >= 0
105 + node.m_root->compare(*m_right, node) <= 0
106@endparblock
107
108@ingroup IntrusiveContainers
109*/
110
111#include "Container.h"
112
113template <class R, class N, class K, ContainerThreadSafety s=ContainerNoSafety, int n = 0> class TreeInNode;
114template <class R, class N, class K, ContainerThreadSafety s=ContainerNoSafety, int n = 0> class TreeInRoot;
115// Forward declared so we can make friend.
116template <class R, class N, class K, ContainerThreadSafety s, int n = 0> class BalTreeInNode;
117
118/**
119@class TreeInRoot
120
121Intrusive Binary Tree, Root.
122
123@tparam R The class that will be the owner of the Tree. Must derive from TreeInRoot<R, N, K, n>
124@tparam N The class that will be the nodes of the Tree. Must derive from TreeInNode<R, N, K, n>
125@tparam K The class defining the Key used to lookup Nodes in the tree.
126@tparam s The ContainerThreadSafety value to define the thread safety model of the Container
127@tparam n A numerical parameter to allow a give List/Node combination to have multiple list-node relationships. Defaults to 0 if not provided.
128
129@invariant
130@parblock
131+ if m_base != nullptr:
132 + m_base->m_root == this.
133 + m_base->m_parent == nullptr
134@endparblock
135
136@see TreeInNode
137@ingroup IntrusiveContainers
138
139@dotfile TreeIn_Structure.dot "Tree Structure"
140Summary:
141+ Root:
142 + Base pointer to the Base node of the Tree
143+ Node
144 + (Red) Nodes have a Root pointer to the Root structure for the tree
145 + (Blue) Parent pointer to the Node leading to the base of the Tree.
146 + The node will be on the Left or Right of that Parent.
147 + The Base node will have a null parent.
148 + Left pointer to the subtree of Nodes that are less than this node
149 + Right pointer to the subtree of Nodes that are greater than this node
150
151
152*/
153template <class R, class N, class K, ContainerThreadSafety s, int n>
154class TreeInRoot : public Container<s> {
155 friend class TreeInNode<R, N, K, s, n>;
156 friend class BalTreeInNode<R, N, K, s, n>; ///< Let Balancer get to us.
157 typedef class TreeInRoot<R, N, K, s, n> Root; ///< Type of TreeInRoot
158 typedef class TreeInNode<R, N, K, s, n> Node; ///< Type of DListIInNode
159protected:
160 TreeInRoot();
161 virtual ~TreeInRoot();
162
163 // These two member functions to be provided by the user.
164 /**
165 * Compare Nodes
166 * Should return >0 if node2 > node1, and <0 if node2 < node1, 0 if equal
167 */
168 int compare(N const& node1, N const& node2) const;
169 /**
170 * Compare Key to node
171 * Should return >0 if key > node, <0 if key < node, 0 if key == node
172 */
173 int compareKey(N const& node, K key) const;
174
175 virtual void add(N& node);
176 void add(N* node);
177 void remove(N& node);
178 void remove(N* node);
179 N* find(K key) const;
180 N* findPlus(K key) const;
181 N* findMinus(K key) const;
182
183 N* base() const { return m_base; }
184 N* first() const;
185 N* last() const;
186
187 bool check() const override;
188
189 // Critical Sections used to Update the Container
190 unsigned writeLock(bool upgrade) const { return Container<s>::writeLock(upgrade); }
191 void writeUnlock(unsigned save) const { Container<s>::writeUnlock(save); }
192 // Critical Section used to Read/Search the Container
193 unsigned readLock(bool upgrade) const { return Container<s>::readLock(upgrade); }
194 void readUnlock(unsigned save) const { Container<s>::readUnlock(save);}
195
196private:
197 N* m_base; ///< Pointer to root node on tree.
198};
199
200/**
201@class TreeInNode
202Intrusive Binary Tree, Node.
203
204@tparam R The class that will be the owner of the List. Must derive from TreeInRoot<R, N, K, n>
205@tparam N The class that will be the nodes of the List. Must derive from TreeInNode<R, N, K, n>
206@tparam K The class defining the Key used to lookup Nodes in the tree.
207@tparam s The ContainerThreadSafety value to define the thread safety model of the Container
208@tparam n A numerical parameter to allow a give List/Node combination to have multiple list-node relationships. Defaults to 0 if not provided.
209
210@invariant
211@parblock
212+ if m_root == NULL: // Free Node
213 + m_parent == NULL
214 + m_left == NULL
215 + m_right == NULL
216+ if m_root != NULL and m_parent == NULL // Base Node
217 + m_root->m_base == this
218+ if m_parent != nullptr: // Child Node
219 + Either m_parent->m_left or parent->m_right == this
220+ if m_left != nullptr
221 + m_left->m_parent = this
222 + m_left->m_root == m_root
223 + m_root->compare(*this, *m_left) <= 0
224 + m_root->compare(*m_left, *this) >= 0
225+ if m_right != nullptr:
226 + m_right->m_parent = this
227 + m_right->m_root == m_root
228 + m_root->compare(*this, *m_right) >= 0
229 + m_root->compare(*m_right, *this) <= 0
230@endparblock
231
232@see TreeInRoot
233@ingroup IntrusiveContainers
234
235@dotfile TreeIn_Structure.dot "Tree Structure"
236
237Summary:
238+ Root:
239 + Base pointer to the Base node of the Tree
240+ Node
241 + (Red) Nodes have a Root pointer to the Root structure for the tree
242 + (Blue) Parent pointer to the Node leading to the base of the Tree.
243 + The node will be on the Left or Right of that Parent.
244 + The Base node will have a null parent.
245 + Left pointer to the subtree of Nodes that are less than this node
246 + Right pointer to the subtree of Nodes that are greater than this node
247
248
249*/
250/*
251@verbatim
252 +------+
253Root: /-------->| Root |<----------\
254B: Base | +------+ |
255 | B | ^ |
256 | | | x |
257 | v | R | P |
258 | +--------------+ |
259Node: | | Node:Base | |
260R: Root | +--------------+ |
261P: Parent | L | ^ R | ^ |
262L: Left | | | | | |
263R: Right | / / \ \ |
264 | / / \ \ |
265 | / / \ \ |
266 | / / \ \ |
267 | | | | | |
268 R | v | P v | P | R
269 +--------------+ +--------------+
270 | Node:Left | | Node:Right |
271 +--------------+ +--------------+
272@endverbatim
273*/
274
275template <class R, class N, class K, ContainerThreadSafety s, int n>
276class TreeInNode : public ContainerNode<s> {
277 friend class TreeInRoot<R, N, K, s, n>;
278 friend class BalTreeInNode<R, N, K, s, n>; ///< Let Balancer get to us.
279 typedef class TreeInRoot<R, N, K, s, n> Root; ///< Type of TreeInRoot
280 typedef class TreeInNode<R, N, K, s, n> Node; ///< Type of DListIInNode
281protected:
282 TreeInNode(); // No default add as that needs our Parent already constructed
283 virtual ~TreeInNode();
284
285 void addTo(R& root);
286 void addTo(R* root);
287 virtual void remove(); // Virtual so "fancier" trees can rebalence
288
289 R* root() const { return m_root; } ///< Return pointer to tree we are on.
290 N* parent() const { return m_parent; }
291 N* left() const { return m_left; }
292 N* right() const { return m_right; }
293 N* next() const;
294 N* prev() const;
295
296 void setRoot(R* root) { m_root = root; ContainerNode<s>::setRoot(static_cast<Root*>(root)); }
297
298 bool check() const override;
299 /**
300 * Hook to allow Balanced trees to rebalance from current node, just changed
301 */
302 virtual void rebalance() { return; }
303 void resort();
304
305 // Critical Sections used to Update the Container
306 unsigned writeLock(bool upgrade) const { return ContainerNode<s>::writeLock(upgrade); }
307 void writeUnlock(unsigned save) const { ContainerNode<s>::writeUnlock(save); }
308 // Critical Section used to Read/Search the Container
309 unsigned readLock(bool upgrade) const { return ContainerNode<s>::readLock(upgrade); }
310 void readUnlock(unsigned save) const { ContainerNode<s>::readUnlock(save);}
311
312private:
313 R* m_root; ///< Pointer to tree we are on.
314 N* m_parent; ///< Pointer to parent node on tree.
315 N* m_left; ///< Pointer to left (lesser) child node on tree.
316 N* m_right; ///< Pointer to right (greater) child node on tree.
317};
318
319#endif
Intrusive Container Documentation and Base Class.
Intrusive Binary Tree, Node.
Definition BalTreeIn.h:222
Base Container Class.
Definition Container.h:192
unsigned writeLock(bool upgrade) const
Obtain a write lock.
unsigned readLock(bool upgradable) const
Obtain a read lock.
void readUnlock(unsigned code) const
Release the read lock that was held.
void writeUnlock(unsigned code) const
Release write lock.
Base Container Node Class.
Definition Container.h:255
unsigned readLock(bool upgradable) const
void setRoot(C *root)
Set our Container.
Definition Container.h:272
void readUnlock(unsigned code) const
unsigned writeLock(bool upgrade) const
void writeUnlock(unsigned code) const
Intrusive Binary Tree, Node.
Definition TreeIn.h:276
N * right() const
Definition TreeIn.h:292
void readUnlock(unsigned save) const
Definition TreeIn.h:310
bool check() const override
Definition TreeIn.hpp:182
virtual ~TreeInNode()
Destructor.
Definition TreeIn.hpp:671
N * m_left
Pointer to left (lesser) child node on tree.
Definition TreeIn.h:315
void resort()
void setRoot(R *root)
Definition TreeIn.h:296
N * prev() const
Return previous node in sort sequence.
Definition TreeIn.hpp:229
R * m_root
Pointer to tree we are on.
Definition TreeIn.h:313
unsigned writeLock(bool upgrade) const
Definition TreeIn.h:306
virtual void remove()
Remove node from whatever tree it is on, if it is on a tree.
Definition TreeIn.hpp:335
class TreeInNode< R, N, K, s, n > Node
Type of DListIInNode.
Definition TreeIn.h:280
N * m_right
Pointer to right (greater) child node on tree.
Definition TreeIn.h:316
N * parent() const
Definition TreeIn.h:290
unsigned readLock(bool upgrade) const
Definition TreeIn.h:309
N * m_parent
Pointer to parent node on tree.
Definition TreeIn.h:314
N * next() const
Return node next in sort sequence.
Definition TreeIn.hpp:194
void addTo(R &root)
Add ourself to a tree.
Definition TreeIn.hpp:513
class TreeInRoot< R, N, K, s, n > Root
Type of TreeInRoot.
Definition TreeIn.h:279
N * left() const
Definition TreeIn.h:291
R * root() const
Return pointer to tree we are on.
Definition TreeIn.h:289
TreeInNode()
Constructor.
Definition TreeIn.hpp:657
void writeUnlock(unsigned save) const
Definition TreeIn.h:307
virtual void rebalance()
Hook to allow Balanced trees to rebalance from current node, just changed.
Definition TreeIn.h:302
Intrusive Binary Tree, Root.
Definition TreeIn.h:154
int compare(N const &node1, N const &node2) const
Compare Nodes Should return >0 if node2 > node1, and <0 if node2 < node1, 0 if equal.
N * base() const
Definition TreeIn.h:183
class TreeInRoot< R, N, K, s, n > Root
Type of TreeInRoot.
Definition TreeIn.h:157
N * last() const
Definition TreeIn.hpp:276
void remove(N &node)
Remove Node from List.
Definition TreeIn.hpp:417
N * m_base
Pointer to root node on tree.
Definition TreeIn.h:197
virtual ~TreeInRoot()
Destructor.
Definition TreeIn.hpp:626
N * find(K key) const
find a node
Definition TreeIn.hpp:539
void readUnlock(unsigned save) const
Definition TreeIn.h:194
class TreeInNode< R, N, K, s, n > Node
Type of DListIInNode.
Definition TreeIn.h:158
unsigned writeLock(bool upgrade) const
Definition TreeIn.h:190
bool check() const override
Definition TreeIn.hpp:185
int compareKey(N const &node, K key) const
Compare Key to node Should return >0 if key > node, <0 if key < node, 0 if key == node.
unsigned readLock(bool upgrade) const
Definition TreeIn.h:193
TreeInRoot()
Constructor.
Definition TreeIn.hpp:613
N * findMinus(K key) const
find a node, or the node that would be just lower than this node
Definition TreeIn.hpp:559
N * first() const
Definition TreeIn.hpp:261
N * findPlus(K key) const
find a node, r the node that would be just above this node.
Definition TreeIn.hpp:585
virtual void add(N &node)
Add node to our tree, note trees are sorted by the compare member function which needs to be implemen...
Definition TreeIn.hpp:450
void writeUnlock(unsigned save) const
Definition TreeIn.h:191