Modernized GAlib  3.0.0 current
GATreeBASE.h
1 // $Header$
2 /* ----------------------------------------------------------------------------
3  treebase.h
4  mbwall 25nov94
5  Copyright 1995 Massachusetts Institute of Technology
6 
7  DESCRIPTION:
8  This defines the tree objects.
9 ---------------------------------------------------------------------------- */
10 #ifndef _ga_treebase_h_
11 #define _ga_treebase_h_
12 
13 #include <GANode.h>
14 
15 /* ----------------------------------------------------------------------------
16  GATreeBASE
17 -------------------------------------------------------------------------------
18  This is the base tree class from which template trees are derived. This
19 object does no memory management - it just keeps track of a tree structure.
20 Whoever calls the members of this object is responsible for allocating and
21 deallocating the memory associated with each node.
22  This class does not define any of the iteration operators for traversing the
23 tree. That is left to the iterator friend of this class.
24  We have to break through the const-ness of the tree in order to make things
25 work properly. When you ask for the size of a tree, you don't change the size
26 but you do (possibly) change the value of the sz member. This doesn't change
27 the state of the tree, so it is, in effect, a const-correct operation. But
28 const is too strict, so we have to work around it. See the size() definition
29 to see how this is done.
30  Beware that when you copy this object, you copy pointers, NOT the contents of
31 the pointers. You cannot simply say tree1 = tree2 or GATreeBASE t = tree1. If
32 you do, you'll get a copy of the tree object but not a copy of the tree (the
33 copy will point to the same tree as the original).
34 
35 creation
36  Create a tree by passing a root node. If you don't pass a root node, then
37  the next node assigned to the tree with an insert or append operation will
38  become the root node (regardless of the idx node you pass).
39 
40 insert
41  Stick a node into the tree. Where the node goes depends on the second node
42  and the value of the flag. There are three flag values: before, after, and
43  below. The flag specifies where the new node should go relative to the old
44  node. If oldnode is the root node, the only valid value for flag is below.
45  If there are already children on a node, specifying below puts the new node
46  at the end of the row of children (it becomes the youngest sibling). If you
47  don't pass a value for flag, it defaults to below. The syntax for using the
48  insert method looks like this:
49 
50  mytree.insert(newnode, oldnode, GATreeBASE::before);
51  mytree.insert(newnode, oldnode);
52 
53  Insertions assume that the node to be inserted has NO siblings. If it does,
54  they will be lost! However, the node MAY have children (a subtree).
55  If the insert was successful, return NO_ERR. If there was a problem,
56  return ERR.
57 
58 remove
59  Remove the specified node from the tree. If the node does not exist, an
60  ERR message is posted and NULL is returned. If the node has children, the
61  children are removed from the tree as well (they stay with the node). A
62  pointer to the node is returned if the removal is successful, otherwise NULL.
63 
64 swaptree
65  Move node a to node b's position in the tree and vice versa. This swap
66  maintains the integrity of all of a's and b's descendents. It checks for
67  ancestry conflicts so that you cannot swap a node with one of its
68  descendents. You can swap nodes in different trees, but if you do, be sure
69  to check for root nodes! The swap routine can set only the root node of the
70  current tree - it doesn't know about the root node of the other tree, so
71  you'll have to reset that one.
72  If the swap was successful, return NO_ERR. If there was a problem,
73  return ERR.
74 
75 swapnode
76  Switch nodes a and b, leaving their subtrees (if any) in their original
77  positions (the subtrees don't follow a and b).
78  If the swap was successful, return NO_ERR. If there was a problem,
79  return ERR.
80 
81 size
82  How many nodes are in the tree? We keep a flag to tell us if any operation
83  has been performed that would require a recalculation of the size. If you
84  change the contents of the tree using any method other than those in this
85  object (which you could do, by the way) then you risk screwing up the count.
86 
87 depth
88  How many levels (generations) are there in the tree?
89 ---------------------------------------------------------------------------- */
91 {
92  public:
93  enum Location
94  {
95  ROOT = 0,
96  BEFORE,
97  AFTER,
98  BELOW
99  }; // values for 'where' to insert
100  enum
101  {
102  NO_ERR = 0,
103  ERR = -1
104  }; // returns codes for tree funcs
105 
106  GATreeBASE()
107  {
108  rt = nullptr;
109  sz = 0;
110  dpth = 0;
111  csz = 0;
112  cdpth = 0;
113  }
114  explicit GATreeBASE(GANodeBASE *n)
115  {
116  rt = n;
117  csz = 1;
118  cdpth = 1;
119  }
120  GANodeBASE *remove(GANodeBASE *n);
121  int insert(GANodeBASE *n, GANodeBASE *idx, Location where = BELOW);
122  int swaptree(GANodeBASE *a, GANodeBASE *b);
123  int swapnode(GANodeBASE *a, GANodeBASE *b);
124  int size() const;
125  int depth() const;
126  int ancestral(unsigned int i, unsigned int j) const;
127 
128  protected:
129  int sz, dpth; // number of nodes, number of levels in tree
130  short csz, cdpth; // have the contents changed since last update?
131  GANodeBASE *rt; // the root node of the tree
132 
133  private:
134  GATreeBASE(const GATreeBASE &) {} // we don't allow copying
135  GATreeBASE &operator=(const GATreeBASE &) { return *this; } // or op=
136  friend class GATreeIterBASE;
137 };
138 
139 /* ----------------------------------------------------------------------------
140  GATreeIterBASE
141 -------------------------------------------------------------------------------
142  This is the base class for iterators for the tree objects. We define this
143 class separately from the Tree object so that you can have multiple interators
144 for each tree and so that you can more easily customize the traversal
145 algorithms within the iterator. From the object point of view, the way you
146 traverse a tree is independent of how you represent the tree.
147  Like the TreeBASE object, this object doesn't do any memory allocation or
148 deallocation. All we do is provide tree traversal.
149  Notice that we keep a 'current location' in the tree - whatever your last
150 query was is stored as the node, so if you refer to the current member, you'll
151 get your last query.
152  If you pass a NULL node to these routines they will break. In the interest
153 of speed we don't do any error checking.
154 
155 creation
156  Create an iterator by passing either a tree or another iterator. If you pass
157  a tree, the iterator will default to the root node of the tree. If you pass
158  another iterator, the new iterator will point to the same node that the
159  original iterator points to.
160 
161 nchildren
162  Returns the number of children that are direct offspring of the specified
163  node (or current node if none is specified).
164 
165 nsiblings
166  Returns the number of nodes at the same level as the specified or current
167  node. This number includes the specified or current node.
168 
169 current, root, next, prev, parent, child, eldest, youngest, warp
170  Set the iterator to the specified node and return a pointer to the node that
171  the iterator now points to. If current is NULL or a NULL is passed to one of
172  these routines, a NULL is returned the iterator does not move.
173 
174 warp
175  Move the iterator to the node referenced by index. The root node is node '0'
176  then the count increases from there using a depth-first search. This means
177  that any subtree in a tree will have a contiguous chunk of indices.
178 ---------------------------------------------------------------------------- */
180 {
181  public:
183  {
184  node = nullptr;
185  tree = (GATreeBASE *)nullptr;
186  }
187  explicit GATreeIterBASE(const GATreeBASE &t)
188  {
189  tree = &t;
190  node = t.rt;
191  }
193  {
194  tree = i.tree;
195  node = i.node;
196  }
197  void operator()(const GATreeBASE &t)
198  {
199  tree = &t;
200  node = t.rt;
201  }
202  GANodeBASE *current(GANodeBASE *c)
203  {
204  return (c != nullptr ? (node = c) : nullptr);
205  }
206  GANodeBASE *current() { return node; }
207  GANodeBASE *next()
208  {
209  return (node != nullptr ? (node = node->next) : nullptr);
210  }
211  GANodeBASE *next(GANodeBASE *c)
212  {
213  return (c != nullptr ? (node = c->next) : nullptr);
214  }
215  GANodeBASE *prev()
216  {
217  return (node != nullptr ? (node = node->prev) : nullptr);
218  }
219  GANodeBASE *prev(GANodeBASE *c)
220  {
221  return (c != nullptr ? (node = c->prev) : nullptr);
222  }
223  GANodeBASE *parent()
224  {
225  return (node != nullptr ? (node = node->parent) : nullptr);
226  }
227  GANodeBASE *parent(GANodeBASE *c)
228  {
229  return (c != nullptr ? (node = c->parent) : nullptr);
230  }
231  GANodeBASE *child()
232  {
233  return (node != nullptr ? (node = node->child) : nullptr);
234  }
235  GANodeBASE *child(GANodeBASE *c)
236  {
237  return (c != nullptr ? (node = c->child) : nullptr);
238  }
239  GANodeBASE *root() { return (tree != nullptr ? (node = tree->rt) : nullptr); }
240  GANodeBASE *root(GANodeBASE *c);
241  GANodeBASE *eldest()
242  {
243  return (node != nullptr ? (node = eldest(node)) : nullptr);
244  }
245  GANodeBASE *eldest(GANodeBASE *c);
246  GANodeBASE *youngest()
247  {
248  return (node != nullptr ? (node = youngest(node)) : nullptr);
249  }
250  GANodeBASE *youngest(GANodeBASE *c);
251  GANodeBASE *warp(unsigned int);
252  GANodeBASE *warp(const GATreeIterBASE &i)
253  {
254  tree = i.tree;
255  node = nullptr;
256  return (i.node != nullptr ? (node = i.node) : nullptr);
257  }
258  int size() { return (node != nullptr ? size(node) : 0); }
259  int size(GANodeBASE *c);
260  int depth() { return (node != nullptr ? depth(node) : 0); }
261  int depth(GANodeBASE *c);
262  int nchildren() { return (node != nullptr ? nchildren(node) : 0); }
263  int nchildren(GANodeBASE *c);
264  int nsiblings() { return (node != nullptr ? nsiblings(node) : 0); }
265  int nsiblings(GANodeBASE *c);
266 
267  protected:
268  GANodeBASE *node;
269  const GATreeBASE *tree;
270 };
271 
272 #endif
Definition: GATreeBASE.h:91
Definition: GATreeBASE.h:180
This is the basic node object.
Definition: GANode.h:18