Intrusive Containers
TreeIn.hpp
Go to the documentation of this file.
1 #ifndef TreeIn_HPP
2 #define TreeIn_HPP
3 
38 #include "TreeIn.h"
39 
41 #define TREEIN_CHECK 1
42 
43 #if TREEIN_CHECK
44 #include "FreeRTOS.h"
45 #define assert configASSERT
46 #include <iostream>
47 #endif
48 
49 
50 /******************************************************************************************
51 Implementation
52 
53 Note that when we need to convert a List or Node pointer/reference to a TreeInRoot/ListInNode
54 pointer/reference we need to do an explicit static_cast, to avoid ambiquity in the case of
55 classes deriving from multiple versions of TreeInRoot/ListInNode
56 */
57 
58 #if TREEIN_CHECK
59 
61 template <class R, class N, class K, int n> inline void TreeInNode<R, N, K, n>::check() const {
62  N const* me = static_cast<N const*>(this);
63  if (root_) {
64  Root* myroot = root_;
65  if (parent_ == 0) {
66  assert(static_cast<Root*>(root_)->base_ == me);
67  } else {
68  Node* myparent = static_cast<Node*>(parent_);
69  assert(myparent->left_ == me || myparent->right_ == me);
70  assert(myparent->root_ == root_);
71  }
72 
73  if (left_) {
74  Node* myleft = static_cast<Node*>(left_);
75  assert(myleft->parent_ == me);
76  assert(myroot->compare(*me, *left_) <= 0);
77  assert(myroot->compare(*left_, *me) >= 0);
78  }
79 
80  if (right_) {
81  Node* myright = static_cast<Node*>(right_);
82  assert(myright->parent_ == me);
83  assert(myroot->compare(*me, *right_) >= 0);
84  assert(myroot->compare(*right_, *me) <= 0);
85  }
86  } else {
87  assert(parent_ == 0);
88  assert(left_ == 0);
89  assert(right_ == 0);
90  }
91 }
92 
93 template <class R, class N, class K, int n> inline void TreeInRoot<R, N, K, n>::check() const {
94  R const* me = static_cast<R const*>(this);
95  if (base_) {
96  Node* node = static_cast<Node*>(base_);
97  assert(node->root_ == me);
98  assert(node->parent_ == 0);
99  node->check();
100  }
101 }
102 #endif
103 
107 template <class R, class N, class K, int n> inline N* TreeInNode<R, N, K, n>::next() const {
108  N const* node;
109  Node const* mynode;
110  if (right_) {
111  // Node has a right child, next will be leftmost child of right child
112  node = right_;
113  mynode = node;
114  while (mynode->left_) {
115  node = mynode->left_;
116  mynode = node;
117  }
118  return const_cast<N*>(node);
119  }
120  // Node does not have a right child, accend parents chain until we reach a parent we are left linked to.
121  mynode = this;
122  node = static_cast<N const*>(mynode);
123  while (mynode->parent_) {
124  N* parent = mynode->parent_;
125  mynode = parent;
126  if (mynode->left_ == node) {
127  return parent;
128  }
129  node = parent;
130  }
131  return 0;
132 }
133 
137 template <class R, class N, class K, int n> inline N* TreeInNode<R, N, K, n>::prev() const {
138  N const* node;
139  Node const* mynode;
140  if (left_) {
141  // Node has a left child, prev will be rightmost child of left child
142  node = left_;
143  mynode = node;
144  while (mynode->right_) {
145  node = mynode->right_;
146  mynode = node;
147  }
148  return const_cast<N*>(node);
149  }
150  // Node does not have a right child, accend parents chain until we reach a parent we are left linked to.
151  mynode = this;
152  node = static_cast<N const*>(mynode);
153  while (mynode->parent_) {
154  N* parent = mynode->parent_;
155  mynode = parent;
156  if (mynode->right_ == node) {
157  return parent;
158  }
159  node = parent;
160  }
161  return 0;
162 }
163 
164 template <class R, class N, class K, int n> inline N* TreeInRoot<R, N, K, n>::first() const {
165  if (base_ == 0) return 0;
166  N* node = base_;
167  Node* mynode = node;
168  while (mynode->left_) {
169  node = mynode->left_;
170  mynode = node;
171  }
172  return node;
173 }
174 
175 
176 template <class R, class N, class K, int n> inline N* TreeInRoot<R, N, K, n>::last() const {
177  if (base_ == 0) return 0;
178  N* node = base_;
179  Node* mynode = node;
180  while (mynode->right_) {
181  node = mynode->right_;
182  mynode = node;
183  }
184  return node;
185 }
186 
191 template <class R, class N, class K, int n> inline void TreeInNode<R, N, K, n>::remove() {
192  if (root_) {
193  static_cast<Root*>(root_)->check();
194  Node* parent = static_cast<Node*>(parent_);
195  N* newLink = 0;
196  if (left_ == 0) {
197  if (right_ == 0) {
198  // We are child node, we can just unlink
199  } else {
200  // Only have right, link our parent to right
201  newLink = right_;
202  }
203  } else {
204  if (right_ == 0) {
205  // Only have left, link our parent to left
206  newLink = left_;
207  } else {
208  // Have both left and right children, rotate our "previous" into our spot.
209  newLink = prev();
210  Node* nl = static_cast<Node*>(newLink);
211  // Our previous node should have its right linked to our right.
212  // Our previous node's right will be null since it is below us
213  nl->right_ = right_;
214  static_cast<Node*>(right_)->parent_ = newLink;
215 
216  if (newLink != left_){
217  // if our previous is not our direct left, unlink it from its parent
218  // linking in its stead it left.
219 
220  static_cast<Node*>(nl->parent_)->right_ = nl->left_;
221  if (nl->left_){
222  static_cast<Node*>(nl->left_)->parent_ = nl->parent_;
223  }
224  // Link our left into our previous left now that it is open.
225 
226  nl->left_ = left_;
227  static_cast<Node*>(left_)->parent_ = newLink;
228 
229  }
230  }
231  }
232  // link our replacement to our parent.
233  if (newLink) {
234  static_cast<Node*>(newLink)->parent_ = parent_;
235  }
236  // update our parent (or root) to point to our replacement (newLink)
237  if (parent) {
238  if (parent->left_ == static_cast<N*>(this)) {
239  parent->left_ = newLink;
240  } else /*if (parent->right_ == static_cast<N*>(this))*/ {
241  parent->right_ = newLink;
242  }
243  } else {
244  static_cast<Root*>(root_)->base_ = newLink;
245  }
246  static_cast<Root*>(root_)->check();
247  root_ = 0;
248  parent_ = 0;
249  left_ = 0;
250  right_ = 0;
251  check();
252  }
253 }
254 
261 template <class R, class N, class K, int n> inline void TreeInRoot<R, N, K, n>::remove(N& node) {
262  Node& mynode = static_cast<Node&>(node);
263  if (mynode.root_ == this) {
264  // Only remove if node is on this list.
265  mynode.remove();
266  }
267 }
268 
269 
277 template <class R, class N, class K, int n_> inline void TreeInRoot<R, N, K, n_>::remove(N* node) {
278  if (node != 0) remove(*node);
279 }
280 
289 template<class R, class N, class K, int n> inline void TreeInRoot<R, N, K, n>::add(N& node) {
290  Node& mynode = node;
291  if (mynode.root_ == this) return; // if already here, do nothing.
292  if (mynode.root_ != 0) mynode.remove(); // if on a different tree, remove.
293  if (base_) {
294  N* nodebase = base_;
295  while (1) {
296  Node* mynodebase = nodebase;
297  int cmp = compare(*nodebase, node);
298  if (cmp < 0) {
299  if (mynodebase->left_) {
300  nodebase = mynodebase->left_;
301  } else {
302  mynodebase->left_ = &node;
303  mynode.parent_ = nodebase;
304  break;
305  }
306  } else {
307  if (mynodebase->right_) {
308  nodebase = mynodebase->right_;
309  } else {
310  mynodebase->right_ = &node;
311  mynode.parent_ = nodebase;
312  break;
313  }
314  }
315  }
316  } else {
317  // Tree Empty, so simple to add
318  base_ = &node;
319  Node& mynode = node;
320  mynode.parent_ = 0;
321  }
322  mynode.root_ = static_cast<R*>(this);
323  mynode.left_ = 0;
324  mynode.right_ = 0;
325  check();
326 }
327 
336 template<class R, class N, class K, int n_> inline void TreeInRoot<R, N, K, n_>::add(N* node) {
337  if (node != 0) add(*node);
338 }
339 
348 template<class R, class N, class K, int n> void TreeInNode<R, N, K, n>::addTo(R& root) {
349  static_cast<Root&>(root).add(*static_cast<N*>(this));
350 }
351 
352 
359 template<class R, class N, class K, int n> void TreeInNode<R, N, K, n>::addTo(R* root) {
360  if (root) {
361  addTo(*root);
362  } else {
363  remove();
364  }
365 }
366 
371 template<class R, class N, class K, int n> N* TreeInRoot<R, N, K, n>::find(K key) const {
372  N* node = base();
373  while(node) {
374  int cmp = compareKey(*node, key);
375  if(cmp == 0) break; // Found the node, return it
376  if(cmp < 0) {
377  node = static_cast<Node*>(node)->left_;
378  } else {
379  node = static_cast<Node*>(node)->right_;
380  }
381  }
382  return node;
383 }
384 
390 template <class R, class N, class K, int n> TreeInRoot<R, N, K, n>::TreeInRoot() :
391 base_(0)
392 {}
393 
402 template <class R, class N, class K, int n> TreeInRoot<R, N, K, n>::~TreeInRoot() {
403  Node* node = base_;
404  while (node) {
405  if (node->left_) {
406  node = node->left_;
407  } else if (node->right_) {
408  node = node->right_;
409  } else {
410  Node* parent = node->parent_;
411  node->left_ = 0;
412  node->right_ = 0;
413  node->parent_ = 0;
414  if (parent) {
415  if (parent->left_ == node) {
416  parent->left_ = 0;
417  }
418  if (parent->right_ == node) {
419  parent->right_ = 0;
420  }
421  }
422  node = parent;
423  }
424  }
425  base_ = 0;
426 }
427 
432 template <class R, class N, class K, int n> TreeInNode<R, N, K, n>::TreeInNode() :
433 root_(0),
434 parent_(0),
435 left_(0),
436 right_(0) {
437 }
438 
444 template <class R, class N, class K, int n> TreeInNode<R, N, K, n>::~TreeInNode() {
445  remove();
446 }
447 #endif
TreeInRoot()
Definition: TreeIn.hpp:390
N * last() const
Definition: TreeIn.hpp:176
void check() const
Definition: TreeIn.hpp:93
void check() const
Definition: TreeIn.hpp:61
N * parent() const
Definition: TreeIn.h:179
void remove(N &node)
Definition: TreeIn.hpp:261
virtual void remove()
Definition: TreeIn.hpp:191
~TreeInNode()
Definition: TreeIn.hpp:444
N * first() const
Definition: TreeIn.hpp:164
virtual void add(N &node)
Definition: TreeIn.hpp:289
N * next() const
Definition: TreeIn.hpp:107
void addTo(R &root)
Definition: TreeIn.hpp:348
Intrusive Binary Tree (unbalenced).
#define assert
Definition: TreeIn.hpp:45
N * prev() const
Definition: TreeIn.hpp:137
~TreeInRoot()
Definition: TreeIn.hpp:402
N * find(K key) const
Definition: TreeIn.hpp:371
TreeInNode()
Definition: TreeIn.hpp:432
R * root() const
Return pointer to list we are on.
Definition: TreeIn.h:178