Modernized GAlib  3.0.0 current
GATree.hpp
1 // $Header$
2 /* ----------------------------------------------------------------------------
3  treetmpl.h
4  mbwall 25feb95
5  Copyright 1995 Massachusetts Institute of Technology
6 
7  DESCRIPTION:
8  This defines the templatized tree objects.
9 ---------------------------------------------------------------------------- */
10 
11 #pragma once
12 
13 #include <GATreeBASE.h>
14 #include <gaerror.h>
15 
16 /* ----------------------------------------------------------------------------
17  GATree
18 -------------------------------------------------------------------------------
19  This object is a container for nodes that have a tree structure. The base
20 tree object is responsible for maintaining the tree heirarchy. This object is
21 responsible for doing the memory management (allocating and de-allocating the
22 nodes in the tree). We insulate the user entirely from nodes - when you use
23 a tree, you don't get nodes back, you get the contents of nodes (ie the user
24 doesn't have to think about the tree parts of a node, they can simply assume
25 that their data is organized into a tree structure).
26  We include an iterator in this object so that you can navigate through the
27 tree. You can create another iterator and assign it to your tree so you can
28 have multiple iterators.
29  All of the actions take place relative to the current location of the
30 embedded iterator. None of the iterators change the state of the tree. Be
31 careful so that you don't end up with an iterator dangling with a pointer to
32 a part of a tree that no longer exists (I would need some kind of reference
33 counting and/or message passing to take care of this at a lower level, and I'm
34 not ready to implement that at this point).
35  For now we allocate nodes on the fly. Eventually I would like to do some
36 better memory management (arrays perhaps?) so we don't have to do so much
37 alloc and dealloc and recursion.
38  We depend on the template-ized GATreeIter routine, thus the declaration.
39 
40 copy
41  Make a copy of the specified tree. Iterator goes to root node (should go to
42  appropriate node in copy, but we don't do that yet).
43 
44 clone
45  Allocate space and make a copy of the tree and return a pointer to the new
46  one. The iterator of the original is not affected. The iterator of the
47  clone is set to the appropriate place in the clone. If you specify a node
48  index when you call clone then a clone of the subtree is made and the
49  iterator in the clone is set to the root node (the top of the subtree).
50 
51 remove
52  Remove the current node (and its subtree) from the tree and stick it into a
53  new tree. Returns a pointer to the new tree. Leaves the original iterator
54  pointing to the eldest child or parent of the node that was removed. Iter
55  of the new tree points to the root node.
56 
57 destroy
58  Destroys the node and subtree where the iterator is currently pointing.
59  Moves the iterator to the eldest sibling or parent of the node that was
60  deleted from the tree.
61 
62 swap
63  Swap nodes in a tree, leaves the nodes' subtrees in place (subtrees do not
64  move with the nodes in the swap).
65 
66 swaptree - tree
67  Swap subtrees referenced by the iterators of this and the second tree. The
68  iterators are reset to point to the new subtrees (same point in the trees,
69  but different nodes due to the swap).
70 
71 swaptree - indices
72  Swap the subtrees referenced by the integer values. Indices must not be
73  related (ie one cannot be ancestor of the other). Iterator is not changed.
74 
75 
76 
77 insert - tree
78  Inserts the contents of tree in to the current tree and removes it from the
79  original tree. Does NOT delete the original tree, but DOES assume
80  responsibility for the memory used by original tree contents.
81 
82 insert - object
83  Inserts the object into a new node relative to the location of the iterator
84 
85 root, current, next, prev, parent, child, warp
86  These iterator methods are defined as access to the embedded iterator of the
87  tree. Use these methods to move the insertion point and to traverse the
88  tree. You can also create other iterators for this tree, but they won't
89  affect the contents.
90 ---------------------------------------------------------------------------- */
91 template <class T> class GATreeIter;
92 
93 /* ----------------------------------------------------------------------------
94 Recursive routines for the Tree objects
95 ---------------------------------------------------------------------------- */
96 // Recursively copy a node, including all of its siblings. This routine copies
97 // a row, then it calls itself to copy the next generation if it finds a next
98 // generation in the next node.
99 template <class T> GANode<T> *_GATreeCopy(GANode<T> *node, GANode<T> *parent)
100 {
101  if (!node)
102  return nullptr;
103 
104  auto *newnode = new GANode<T>(node->contents);
105  newnode->parent = parent;
106  newnode->child = _GATreeCopy(DYN_CAST(GANode<T> *, node->child), newnode);
107 
108  GANode<T> *lasttmp = newnode, *newtmp = nullptr;
109  GANode<T> *tmp = DYN_CAST(GANode<T> *, node->next);
110  while (tmp && tmp != node)
111  {
112  newtmp = new GANode<T>(tmp->contents);
113  newtmp->parent = parent;
114  newtmp->child = _GATreeCopy(DYN_CAST(GANode<T> *, tmp->child), newtmp);
115  newtmp->prev = lasttmp;
116  lasttmp->next = newtmp;
117 
118  lasttmp = newtmp;
119  tmp = DYN_CAST(GANode<T> *, tmp->next);
120  }
121 
122  if (newtmp)
123  {
124  newtmp->next = newnode;
125  newnode->prev = newtmp;
126  }
127  else
128  {
129  newnode->next = newnode;
130  newnode->prev = newnode;
131  }
132 
133  return newnode;
134 }
135 
136 // This routine destroys the specified node, its children, its siblings, and
137 // all of their children, their childrens' siblings, etc. Since we kill off
138 // all of the siblings, we need to set the parent's link to its child to NULL.
139 template <class T> void _GATreeDestroy(GANode<T> *node)
140 {
141  if (!node)
142  return;
143 
144  if (node->parent)
145  node->parent->child = nullptr;
146  _GATreeDestroy(DYN_CAST(GANode<T> *, node->child));
147 
148  GANodeBASE *tmp;
149  while (node->next && node->next != node)
150  {
151  tmp = node->next;
152  node->next = tmp->next;
153  tmp->next->prev = node;
154  _GATreeDestroy(DYN_CAST(GANode<T> *, tmp->child));
155  delete tmp;
156  }
157  delete node;
158 }
159 
160 extern GANodeBASE *_GATreeTraverse(unsigned int, unsigned int &, GANodeBASE *);
161 
162 template <class T> class GATree : public GATreeBASE
163 {
164  public:
165  GATree() : GATreeBASE() { iter(*this); }
166  explicit GATree(const T &t) : GATreeBASE(new GANode<T>(t)), iter(*this) {}
167  GATree(const GATree<T> &orig)
168  {
169  iter(*this);
170  copy(orig);
171  }
172  GATree<T> &operator=(const GATree<T> &orig)
173  {
174  if (&orig != this)
175  copy(orig);
176  return *this;
177  }
178  // The destructor just goes through the tree and deletes every node. As
179  // with
180  // any method that uses the BASE tree, we have to use its members so it
181  // doesn't get messed up.
182  ~GATree()
183  {
184  _GATreeDestroy(DYN_CAST(GANode<T> *, rt));
185  iter.node = nullptr;
186  }
187 
188  // Recursively duplicate a subtree given a base node. This uses the _copy
189  // method (which does a deep and wide copy). Here we just copy a node, then
190  // sic the _copy method on the child if it exists. The parent of the new
191  // node is set to NULL - this makes it a root node in the new tree object.
192  // We do the cloning based on the valued passed to the routine. 0 is the
193  // root node and makes a clone of the entire tree. This routine has no
194  // effect on the iterator in the original tree.
195  // The iterator in the clone is left pointing to the root node of the
196  // clone.
197  GATree<T> *clone(unsigned int i = 0) const
198  {
199  auto *t = new GATree<T>;
200  GANode<T> *node;
201  unsigned int w = 0;
202  if (i == 0)
203  node = DYN_CAST(GANode<T> *, rt);
204  else
205  node = DYN_CAST(GANode<T> *, _GATreeTraverse(i, w, rt));
206  if (!node)
207  return t;
208 
209  auto *newnode = new GANode<T>(node->contents);
210  newnode->child =
211  _GATreeCopy(DYN_CAST(GANode<T> *, node->child), newnode);
212  if (newnode->child)
213  newnode->child->parent = newnode;
214 
215  t->insert(newnode, nullptr, GATreeBASE::ROOT);
216 
217  return t;
218  }
219 
220  // methods that modify the state of the tree
221 
222  // Yes, this is really ugly. We do a complete destruction of the existing
223  // tree then we copy the new one. No caching, no nothing. Oh well. The
224  // iterator is set to the root node - it should be set to the corresponding
225  // node, but I won't do that for now. THIS IS A BUG!
226  void copy(const GATree<T> &orig)
227  {
228  _GATreeDestroy(DYN_CAST(GANode<T> *, rt));
229  rt = _GATreeCopy(DYN_CAST(GANode<T> *, orig.rt), (GANode<T> *)nullptr);
230  iter.node = rt;
231  sz = orig.sz;
232  csz = orig.csz;
233  dpth = orig.dpth;
234  cdpth = orig.cdpth;
235  }
236 
237  // Destroy the specified node and all nodes attached to it looking downward.
238  // This does NOT destroy any nodes above the specified node. If this node
239  // is in a tree, it will be removed before the nuking occurs. This gives
240  // the tree object a chance to flag for any recalculations it might need.
241  // The destroy method effect on the tree as a remove, but it is destructive
242  // (it frees up the memory as well).
243  // We do the nuking recursively, so its not really that efficient. I'll
244  // figure out a better way to track these nodes one of these days.
245  // We use the _destroy routine to do the recursion. _destroy kills all of
246  // the siblings of the node whereas this routine kills only descendents.
247  // This uses the current node as the one to destroy, so be sure to use the
248  // iteration methods to move to the node you want to destroy. Once the node
249  // is gone, we set the current node to the eldest child or parent of the
250  // node that was destroyed.
251  int destroy()
252  {
253  GANodeBASE *node = iter.node;
254  if (!node)
255  return GATreeBASE::NO_ERR;
256  if (node->prev == node || !node->prev)
257  if (node->parent)
258  iter.node = node->parent;
259  else
260  iter.node = nullptr;
261  else
262  iter.eldest();
263  _GATreeDestroy(DYN_CAST(GANode<T> *, node->child));
264  delete GATreeBASE::remove(node);
265  return GATreeBASE::NO_ERR;
266  }
267 
268  // Swap two subtrees. We use the nodes pointed to by the iterators in the
269  // current tree and the one that was passed to us. The TreeBASE swaptree
270  // changes the next, prev, parent, child pointers on the nodes we pass it as
271  // well as the nodes that those nodes point to.
272  // Notice that this routine uses the current location of the iterators to
273  // do its job, so be sure to set them properly before you call this routine!
274  // The iterators are reset to the nodes where the swaps occurred. Sizes
275  // and
276  // depths are possibly changed - the insert method flags them for a recalc.
277  // If an iterator is NULL then we do an insert ONLY if the root node of
278  // that
279  // iterator's tree is NULL. If the tree's root is non-NULL, we don't do
280  // anything (most likely the iterator was unset or badly set).
281  int swaptree(GATree<T> *t)
282  {
283  GANodeBASE *tmp;
284  if (t->iter.node && iter.node)
285  {
286  if (GATreeBASE::swaptree(t->iter.node, iter.node) ==
287  GATreeBASE::ERR)
288  return GATreeBASE::ERR;
289  if (t->rt == t->iter.node)
290  t->rt = iter.node;
291  tmp = t->iter.node;
292  t->iter.node = iter.node;
293  iter.node = tmp;
294 
295  t->csz = 1;
296  t->cdpth = 1; // remember to flag the changes in t!
297  csz = 1;
298  cdpth = 1;
299  }
300  else if (t->iter.node)
301  { // iter.node is NULL, so we have no root
302  if (!rt)
303  { // should always be true at this point
304  tmp = t->GATreeBASE::remove(t->iter.node);
305  // tmp->next = tmp;
306  // tmp->prev = tmp;
307  t->iter.node = nullptr;
308  if (insert(DYN_CAST(GANode<T> *, tmp), nullptr,
309  GATreeBASE::ROOT) == GATreeBASE::ERR)
310  return GATreeBASE::ERR;
311  }
312  }
313  else if (iter.node)
314  { // t's iter is NULL, so it has no root
315  if (!t->rt)
316  { // should always be true
317  tmp = GATreeBASE::remove(iter.node);
318  // tmp->next = tmp;
319  // tmp->prev = tmp;
320  iter.node = nullptr;
321  if (t->insert(DYN_CAST(GANode<T> *, tmp), nullptr,
322  GATreeBASE::ROOT) == GATreeBASE::ERR)
323  return GATreeBASE::ERR;
324  }
325  }
326  // else both t->iter.node and iter.node are NULL, so don't do anything
327  return GATreeBASE::NO_ERR;
328  }
329 
330  // Same as the swaptree above, but this routine uses the node indices to do
331  // the swap. This can be dangerous: if one of the nodes is a decendent of
332  // the other then we could end up with a fragmented tree, so we'll have to
333  // check for that situation. Unfortunately this check slows things down
334  // quite a bit. If one is the ancestor of the other, then we don't do the
335  // swap.
336  // This routine does not affect the size of the tree, but it could change
337  // the
338  // depth of the tree. We leave the iterator where it was pointing before
339  // the swap.
340  int swaptree(unsigned int a, unsigned int b)
341  {
342  unsigned int aw = 0, bw = 0;
343  GANodeBASE *anode = _GATreeTraverse(a, aw, rt);
344  GANodeBASE *bnode = _GATreeTraverse(b, bw, rt);
345  return GATreeBASE::swaptree(anode, bnode);
346  }
347 
348  // Swap two nodes in a tree, leave their subtrees intact. This routine does
349  // not affect the iterator or the size or depth of the tree.
350  int swap(unsigned int a, unsigned int b)
351  {
352  unsigned int aw = 0, bw = 0;
353  GANodeBASE *anode = _GATreeTraverse(a, aw, rt);
354  GANodeBASE *bnode = _GATreeTraverse(b, bw, rt);
355  return GATreeBASE::swapnode(anode, bnode);
356  }
357 
358  // This remove method returns a tree with the removed node as its root. The
359  // node we remove is the current node. We allocate memory for the tree, but
360  // we don't allocate any memory for the node or its children. That is taken
361  // from the previous (this) tree and it no longer has to worry about it. It
362  // is the responsibility of the new tree to delete that memory.
363  // The iterator gets set to the elder child of the node that was removed.
364  // If
365  // there is no elder child, then it gets set to the parent. If no parent,
366  // then it gets set to NULL.
367  // Thank you to Uli Bubenheimer (uli@aisun1.ai.uga.edu) for the bug fix
368  // here.
369  // I forgot to fix the pointers in the root node of the sub-tree.
370  GATree<T> *remove()
371  {
372  auto *t = new GATree<T>;
373  GANode<T> *node = DYN_CAST(GANode<T> *, iter.node);
374  if (!node)
375  return t;
376 
377  if (node->prev != node)
378  iter.eldest();
379  else if (node->parent)
380  iter.parent();
381  else
382  iter.node = nullptr;
383 
384  GANode<T> *tmpnode = DYN_CAST(GANode<T> *, GATreeBASE::remove(node));
385  tmpnode->prev = tmpnode;
386  tmpnode->next = tmpnode;
387  tmpnode->parent = nullptr;
388 
389  t->insert(tmpnode, nullptr, GATreeBASE::ROOT);
390 
391  return t;
392  }
393 
394  int insert(GATree<T> *t, GATreeBASE::Location where = GATreeBASE::BELOW)
395  {
396  if (this == t)
397  {
398  GAErr(GA_LOC, "GATree", "insert", GAError::CannotInsertIntoSelf);
399  return GATreeBASE::ERR;
400  }
401  if (GATreeBASE::insert(t->rt, iter.node, where) == GATreeBASE::ERR)
402  {
403  return GATreeBASE::ERR;
404  }
405  iter.node = (t->rt ? t->rt : iter.node);
406  t->rt = nullptr;
407  t->iter.node = nullptr;
408  return GATreeBASE::NO_ERR;
409  }
410  int insert(const T &t, GATreeBASE::Location where = GATreeBASE::BELOW)
411  {
412  auto *c = new GANode<T>(t);
413  if (GATreeBASE::insert(c, iter.node, where) == GATreeBASE::ERR)
414  {
415  delete c;
416  return GATreeBASE::ERR;
417  }
418  iter.node = c;
419  return GATreeBASE::NO_ERR;
420  }
421 
422  // typesafes on iteration methods. These call the built-in iterator then
423  // return the contents of the now-current node. They do not affect the
424  // state of the tree.
425  T *root() { return iter.root(); }
426  T *current() { return iter.current(); }
427  T *next() { return iter.next(); }
428  T *prev() { return iter.prev(); }
429  T *parent() { return iter.parent(); }
430  T *child() { return iter.child(); }
431  T *eldest() { return iter.eldest(); }
432  T *youngest() { return iter.youngest(); }
433  T *warp(unsigned int i) { return iter.warp(i); }
434  T *warp(const GATreeIter<T> &i)
435  {
436  return ((i.tree == this) ? iter.warp(i) : nullptr);
437  }
438  int nchildren() { return iter.nchildren(); }
439  int nsiblings() { return iter.nsiblings(); }
440 
441  protected:
442  int insert(GANode<T> *n, GANode<T> *idx,
443  GATreeBASE::Location where = GATreeBASE::BELOW)
444  {
445  if (GATreeBASE::insert(n, idx, where) == GATreeBASE::ERR)
446  return GATreeBASE::ERR;
447  iter.node = n;
448  return GATreeBASE::NO_ERR;
449  }
450  GATreeIter<T> iter;
451  friend class GATreeIter<T>;
452 };
453 
454 /* ----------------------------------------------------------------------------
455  GATreeIter
456 -------------------------------------------------------------------------------
457  This is a type-safe derivation of the base TreeIter object. I copied the
458 methods from the base class (I know, a no-no) rather than doing calls to the
459 base class methods.
460  We depend on the template-ized GATree, thus the declaration.
461  Behaviour for the iterator methods is defined as follows. If the current
462 node is null, attempts to access a derived position from the current position
463 will return NULL. The only way to reset the current node is to call the root()
464 locater (you always have to start at the tree root to navigate the tree). If
465 the current node is non-null and the derived node is null, the current node is
466 NOT changed, but NULL is returned.
467  When we create a new tree iterator, it defaults to the same node as the one
468 used to create it. If it is created with a tree as its argument, it defaults
469 to the tree's iterator's current position.
470 ---------------------------------------------------------------------------- */
471 template <class T> class GATree;
472 
473 template <class T> class GATreeIter : public GATreeIterBASE
474 {
475  public:
476  GATreeIter() : GATreeIterBASE() {}
477  explicit GATreeIter(const GATree<T> &t) : GATreeIterBASE(t)
478  {
479  node = t.iter.node;
480  }
481  GATreeIter(const GATreeIter<T> &i) : GATreeIterBASE(i) {}
482  T *current() { return (node ? &((GANode<T> *)node)->contents : nullptr); }
483  T *root()
484  {
485  return (((node = GATreeIterBASE::root()) != nullptr) ? &((GANode<T> *)GATreeIterBASE::root(node))->contents : nullptr);
486  }
487  T *next()
488  {
489  return ((node && node->next) ? &((GANode<T> *)(node = node->next))->contents : nullptr);
490  }
491  T *prev()
492  {
493  return ((node && node->prev) ? &((GANode<T> *)(node = node->prev))->contents : nullptr);
494  }
495  T *parent()
496  {
497  return ((node && node->parent) ? &((GANode<T> *)(node = node->parent))->contents : nullptr);
498  }
499  T *child()
500  {
501  return ((node && node->child) ? &((GANode<T> *)(node = node->child))->contents : nullptr);
502  }
503  T *eldest()
504  {
505  return (node ? &((GANode<T> *)GATreeIterBASE::eldest(node))->contents : nullptr);
506  }
507  T *youngest()
508  {
509  return (node ? &((GANode<T> *)GATreeIterBASE::youngest(node))->contents : nullptr);
510  }
511  T *warp(const GATree<T> &t)
512  {
513  tree = &t;
514  node = t.iter.node;
515  return (t.iter.node ? &((GANode<T> *)(node = t.iter.node))->contents : nullptr);
516  }
517  T *warp(const GATreeIter<T> &i)
518  {
519  tree = i.tree;
520  node = i.node;
521  return (i.node ? &((GANode<T> *)(node = i.node))->contents : nullptr);
522  }
523  T *warp(unsigned int i)
524  {
525  GANodeBASE *n = GATreeIterBASE::warp(i);
526  return (n ? &((GANode<T> *)(node = n))->contents : nullptr);
527  }
528 
529  private:
530  friend class GATree<T>;
531 };
Definition: GATreeBASE.h:91
Definition: GATreeBASE.h:180
Definition: GATree.hpp:474
Definition: GATree.hpp:163
This is the basic node object.
Definition: GANode.h:18
Definition: GANode.h:79