tlds
Transactional Operations for Linked Data Structures
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Tree.hpp
Go to the documentation of this file.
1 /**
2  * Copyright (C) 2011
3  * University of Rochester Department of Computer Science
4  * and
5  * Lehigh University Department of Computer Science and Engineering
6  *
7  * License: Modified BSD
8  * Please see the file LICENSE.RSTM for licensing information
9  */
10 
11 #ifndef TREE_HPP__
12 #define TREE_HPP__
13 
14 #include <climits>
15 #include <api/api.hpp> // need this for malloc and free
16 
17 class RBTree
18 {
19  enum Color { RED, BLACK };
20 
21  // Node of an RBTree
22  struct RBNode
23  {
25  int m_val;
27  int m_ID;
29 
30  // basic constructor
31  RBNode(Color color = BLACK,
32  long val = -1,
33  RBNode* parent = NULL,
34  long ID = 0,
35  RBNode* child0 = NULL,
36  RBNode* child1 = NULL)
37  : m_color(color), m_val(val), m_parent(parent), m_ID(ID)
38  {
39  m_child[0] = child0;
40  m_child[1] = child1;
41  }
42  };
43 
44  // helper functions for sanity checks
45  static int blackHeight(const RBNode* x);
46  static bool redViolation(const RBNode* p_r, const RBNode* x);
47  static bool validParents(const RBNode* p, int xID, const RBNode* x);
48  static bool inOrder(const RBNode* x, int lowerBound, int upperBound);
49 
50  public:
52 
53  RBTree();
54 
55  // standard IntSet methods
57  bool lookup(int val TM_ARG) const;
58 
60  void insert(int val TM_ARG);
61 
63  void remove(int val TM_ARG);
64 
66  void modify(int val TM_ARG);
67 
68  bool isSane() const;
69 };
70 
71 // binary search for the node that has v as its value
72 bool RBTree::lookup(int v TM_ARG) const
73 {
74  // find v
75  RBNode* x = TM_READ(sentinel->m_child[0]);
76  while (x != NULL) {
77  long xval = TM_READ(x->m_val);
78  if (xval == v)
79  return true;
80  else
81  x = TM_READ(x->m_child[(v < xval) ? 0 : 1]);
82  }
83  return false;
84 }
85 
87 {
88  if (lookup(v TM_PARAM))
89  remove(v TM_PARAM);
90  else
91  insert(v TM_PARAM);
92 }
93 
94 // insert a node with v as its value if no such node exists in the tree
96 {
97  // find insertion point
98  const RBNode* curr(sentinel);
99  int cID = 0;
100  RBNode* child(TM_READ(curr->m_child[cID]));
101 
102  while (child != NULL) {
103  long cval = TM_READ(child->m_val);
104  if (cval == v)
105  return; // don't add existing key
106  cID = v < cval ? 0 : 1;
107  curr = child;
108  child = TM_READ(curr->m_child[cID]);
109  }
110 
111  // create the new node ("child") and attach it as curr->child[cID]
112  child = (RBNode*)TM_ALLOC(sizeof(RBNode));
113  child->m_color = RED;
114  child->m_val = v;
115  child->m_parent = const_cast<RBNode*>(curr);
116  child->m_ID = cID;
117  child->m_child[0] = NULL;
118  child->m_child[1] = NULL;
119 
120  RBNode* curr_rw = const_cast<RBNode*>(curr);
121  const RBNode* child_r(child);
122  TM_WRITE(curr_rw->m_child[cID], child);
123 
124  // balance the tree
125  while (true) {
126  const RBNode* parent_r(TM_READ(child_r->m_parent));
127  // read the parent of curr as gparent
128  const RBNode* gparent_r(TM_READ(parent_r->m_parent));
129 
130  if ((gparent_r == sentinel) ||
131  (BLACK == TM_READ(parent_r->m_color)))
132  break;
133 
134  // cache the ID of the parent
135  int pID = TM_READ(parent_r->m_ID);
136  // get parent's sibling as aunt
137  const RBNode* aunt_r(TM_READ(gparent_r->m_child[1-pID]));
138  // gparent and parent will be written on all control paths
139  RBNode* gparent_w = const_cast<RBNode*>(gparent_r);
140  RBNode* parent_w = const_cast<RBNode*>(parent_r);
141 
142  if ((aunt_r != NULL) && (RED == TM_READ(aunt_r->m_color))) {
143  // set parent and aunt to BLACK, grandparent to RED
144  TM_WRITE(parent_w->m_color, BLACK);
145  RBNode* aunt_rw = const_cast<RBNode*>(aunt_r);
146  TM_WRITE(aunt_rw->m_color, BLACK);
147  TM_WRITE(gparent_w->m_color, RED);
148  // now restart loop at gparent level
149  child_r = gparent_w;
150  continue;
151  }
152 
153  int cID = TM_READ(child_r->m_ID);
154  if (cID != pID) {
155  // promote child
156  RBNode* child_rw = const_cast<RBNode*>(child_r);
157  RBNode* baby(TM_READ(child_rw->m_child[1-cID]));
158  // set child's child to parent's cID'th child
159  TM_WRITE(parent_w->m_child[cID], baby);
160  if (baby != NULL) {
161  RBNode* baby_w(baby);
162  TM_WRITE(baby_w->m_parent, parent_w);
163  TM_WRITE(baby_w->m_ID, cID);
164  }
165  // move parent into baby's position as a child of child
166  TM_WRITE(child_rw->m_child[1-cID], parent_w);
167  TM_WRITE(parent_w->m_parent, child_rw);
168  TM_WRITE(parent_w->m_ID, 1-cID);
169  // move child into parent's spot as pID'th child of gparent
170  TM_WRITE(gparent_w->m_child[pID], child_rw);
171  TM_WRITE(child_rw->m_parent, gparent_w);
172  TM_WRITE(child_rw->m_ID, pID);
173  // promote(child_rw);
174  // now swap child with curr and continue
175  const RBNode* t(child_rw);
176  child_r = parent_w;
177  parent_w = const_cast<RBNode*>(t);
178  }
179 
180  TM_WRITE(parent_w->m_color, BLACK);
181  TM_WRITE(gparent_w->m_color, RED);
182  // promote parent
183  RBNode* ggparent_w(TM_READ(gparent_w->m_parent));
184  int gID = TM_READ(gparent_w->m_ID);
185  RBNode* ochild = TM_READ(parent_w->m_child[1 - pID]);
186  // make gparent's pIDth child ochild
187  TM_WRITE(gparent_w->m_child[pID], ochild);
188  if (ochild != NULL) {
189  RBNode* ochild_w(ochild);
190  TM_WRITE(ochild_w->m_parent, gparent_w);
191  TM_WRITE(ochild_w->m_ID, pID);
192  }
193  // make gparent the 1-pID'th child of parent
194  TM_WRITE(parent_w->m_child[1-pID], gparent_w);
195  TM_WRITE(gparent_w->m_parent, parent_w);
196  TM_WRITE(gparent_w->m_ID, 1-pID);
197  // make parent the gIDth child of ggparent
198  TM_WRITE(ggparent_w->m_child[gID], parent_w);
199  TM_WRITE(parent_w->m_parent, ggparent_w);
200  TM_WRITE(parent_w->m_ID, gID);
201  // promote(parent_w);
202  }
203 
204  // now just set the root to black
205  const RBNode* sentinel_r(sentinel);
206  const RBNode* root_r(TM_READ(sentinel_r->m_child[0]));
207  if (TM_READ(root_r->m_color) != BLACK) {
208  RBNode* root_rw = const_cast<RBNode*>(root_r);
209  TM_WRITE(root_rw->m_color, BLACK);
210  }
211 }
212 
213 // remove the node with v as its value if it exists in the tree
215 {
216  // find v
217  const RBNode* sentinel_r(sentinel);
218  // rename x_r to x_rw, x_rr to x_r
219  const RBNode* x_r(TM_READ(sentinel_r->m_child[0]));
220 
221  while (x_r != NULL) {
222  int xval = TM_READ(x_r->m_val);
223  if (xval == v)
224  break;
225  x_r = TM_READ(x_r->m_child[v < xval ? 0 : 1]);
226  }
227 
228  // if we found v, remove it. Otherwise return
229  if (x_r == NULL)
230  return;
231 
232  RBNode* x_rw = const_cast<RBNode*>(x_r); // upgrade to writable
233 
234  // ensure that we are deleting a node with at most one child
235  // cache value of rhs child
236  RBNode* xrchild(TM_READ(x_rw->m_child[1]));
237  if ((xrchild != NULL) && (TM_READ(x_rw->m_child[0]) != NULL)) {
238  // two kids! find right child's leftmost child and swap it
239  // with x
240  const RBNode* leftmost_r(TM_READ(x_rw->m_child[1]));
241 
242  while (TM_READ(leftmost_r->m_child[0]) != NULL)
243  leftmost_r = TM_READ(leftmost_r->m_child[0]);
244 
245  TM_WRITE(x_rw->m_val, TM_READ(leftmost_r->m_val));
246  x_rw = const_cast<RBNode*>(leftmost_r);
247  }
248 
249  // extract x from the tree and prep it for deletion
250  RBNode* parent_rw(TM_READ(x_rw->m_parent));
251  int cID = (TM_READ(x_rw->m_child[0]) != NULL) ? 0 : 1;
252  RBNode* child = TM_READ(x_rw->m_child[cID]);
253  // make child the xID'th child of parent
254  int xID = TM_READ(x_rw->m_ID);
255  TM_WRITE(parent_rw->m_child[xID], child);
256  if (child != NULL) {
257  RBNode* child_w(child);
258  TM_WRITE(child_w->m_parent, parent_rw);
259  TM_WRITE(child_w->m_ID, xID);
260  }
261 
262  // fix black height violations
263  if ((BLACK == TM_READ(x_rw->m_color)) && (child != NULL)) {
264  const RBNode* c_r(child);
265  if (RED == TM_READ(c_r->m_color)) {
266  RBNode* c_rw = const_cast<RBNode*>(c_r);
267  TM_WRITE(x_rw->m_color, RED);
268  TM_WRITE(c_rw->m_color, BLACK);
269  }
270  }
271 
272  // rebalance
273  RBNode* curr(x_rw);
274  while (true) {
275  parent_rw = TM_READ(curr->m_parent);
276  if ((parent_rw == sentinel) || (RED == TM_READ(curr->m_color)))
277  break;
278  int cID = TM_READ(curr->m_ID);
279  RBNode* sibling_w(TM_READ(parent_rw->m_child[1 - cID]));
280 
281  // we'd like y's sibling s to be black
282  // if it's not, promote it and recolor
283  if (RED == TM_READ(sibling_w->m_color)) {
284  /*
285  Bp Bs
286  / \ / \
287  By Rs => Rp B2
288  / \ / \
289  B1 B2 By B1
290  */
291  TM_WRITE(parent_rw->m_color, RED);
292  TM_WRITE(sibling_w->m_color, BLACK);
293  // promote sibling
294  RBNode* gparent_w(TM_READ(parent_rw->m_parent));
295  int pID = TM_READ(parent_rw->m_ID);
296  RBNode* nephew_w(TM_READ(sibling_w->m_child[cID]));
297  // set nephew as 1-cID child of parent
298  TM_WRITE(parent_rw->m_child[1-cID], nephew_w);
299  TM_WRITE(nephew_w->m_parent, parent_rw);
300  TM_WRITE(nephew_w->m_ID, (1-cID));
301  // make parent the cID child of the sibling
302  TM_WRITE(sibling_w->m_child[cID], parent_rw);
303  TM_WRITE(parent_rw->m_parent, sibling_w);
304  TM_WRITE(parent_rw->m_ID, cID);
305  // make sibling the pID child of gparent
306  TM_WRITE(gparent_w->m_child[pID], sibling_w);
307  TM_WRITE(sibling_w->m_parent, gparent_w);
308  TM_WRITE(sibling_w->m_ID, pID);
309  // reset sibling
310  sibling_w = nephew_w;
311  }
312 
313  RBNode* n = TM_READ(sibling_w->m_child[1 - cID]);
314  const RBNode* n_r(n); // if n is null, n_r will be null too
315  if ((n != NULL) && (RED == TM_READ(n_r->m_color))) {
316  // the far nephew is red
317  RBNode* n_rw(n);
318  /*
319  ?p ?s
320  / \ / \
321  By Bs => Bp Bn
322  / \ / \
323  ?1 Rn By ?1
324  */
325  TM_WRITE(sibling_w->m_color, TM_READ(parent_rw->m_color));
326  TM_WRITE(parent_rw->m_color, BLACK);
327  TM_WRITE(n_rw->m_color, BLACK);
328  // promote sibling_w
329  RBNode* gparent_w(TM_READ(parent_rw->m_parent));
330  int pID = TM_READ(parent_rw->m_ID);
331  RBNode* nephew(TM_READ(sibling_w->m_child[cID]));
332  // make nephew the 1-cID child of parent
333  TM_WRITE(parent_rw->m_child[1-cID], nephew);
334  if (nephew != NULL) {
335  RBNode* nephew_w(nephew);
336  TM_WRITE(nephew_w->m_parent, parent_rw);
337  TM_WRITE(nephew_w->m_ID, 1-cID);
338  }
339  // make parent the cID child of the sibling
340  TM_WRITE(sibling_w->m_child[cID], parent_rw);
341  TM_WRITE(parent_rw->m_parent, sibling_w);
342  TM_WRITE(parent_rw->m_ID, cID);
343  // make sibling the pID child of gparent
344  TM_WRITE(gparent_w->m_child[pID], sibling_w);
345  TM_WRITE(sibling_w->m_parent, gparent_w);
346  TM_WRITE(sibling_w->m_ID, pID);
347  break; // problem solved
348  }
349 
350  n = TM_READ(sibling_w->m_child[cID]);
351  n_r = n;
352  if ((n != NULL) && (RED == TM_READ(n_r->m_color))) {
353  /*
354  ?p ?p
355  / \ / \
356  By Bs => By Bn
357  / \ \
358  Rn B1 Rs
359  \
360  B1
361  */
362  RBNode* n_rw = const_cast<RBNode*>(n_r);
363  TM_WRITE(sibling_w->m_color, RED);
364  TM_WRITE(n_rw->m_color, BLACK);
365  RBNode* t = sibling_w;
366  // promote n_rw
367  RBNode* gneph(TM_READ(n_rw->m_child[1-cID]));
368  // make gneph the cID child of sibling
369  TM_WRITE(sibling_w->m_child[cID], gneph);
370  if (gneph != NULL) {
371  RBNode* gneph_w(gneph);
372  TM_WRITE(gneph_w->m_parent, sibling_w);
373  TM_WRITE(gneph_w->m_ID, cID);
374  }
375  // make sibling the 1-cID child of n
376  TM_WRITE(n_rw->m_child[1 - cID], sibling_w);
377  TM_WRITE(sibling_w->m_parent, n_rw);
378  TM_WRITE(sibling_w->m_ID, 1 - cID);
379  // make n the 1-cID child of parent
380  TM_WRITE(parent_rw->m_child[1 - cID], n_rw);
381  TM_WRITE(n_rw->m_parent, parent_rw);
382  TM_WRITE(n_rw->m_ID, 1 - cID);
383  sibling_w = n_rw;
384  n_rw = t;
385 
386  // now the far nephew is red... copy of code from above
387  TM_WRITE(sibling_w->m_color, TM_READ(parent_rw->m_color));
388  TM_WRITE(parent_rw->m_color, BLACK);
389  TM_WRITE(n_rw->m_color, BLACK);
390  // promote sibling_w
391  RBNode* gparent_w(TM_READ(parent_rw->m_parent));
392  int pID = TM_READ(parent_rw->m_ID);
393  RBNode* nephew(TM_READ(sibling_w->m_child[cID]));
394  // make nephew the 1-cID child of parent
395  TM_WRITE(parent_rw->m_child[1-cID], nephew);
396  if (nephew != NULL) {
397  RBNode* nephew_w(nephew);
398  TM_WRITE(nephew_w->m_parent, parent_rw);
399  TM_WRITE(nephew_w->m_ID, 1-cID);
400  }
401  // make parent the cID child of the sibling
402  TM_WRITE(sibling_w->m_child[cID], parent_rw);
403  TM_WRITE(parent_rw->m_parent, sibling_w);
404  TM_WRITE(parent_rw->m_ID, cID);
405  // make sibling the pID child of gparent
406  TM_WRITE(gparent_w->m_child[pID], sibling_w);
407  TM_WRITE(sibling_w->m_parent, gparent_w);
408  TM_WRITE(sibling_w->m_ID,pID);
409 
410  break; // problem solved
411  }
412  /*
413  ?p ?p
414  / \ / \
415  Bx Bs => Bp Rs
416  / \ / \
417  B1 B2 B1 B2
418  */
419 
420  TM_WRITE(sibling_w->m_color, RED); // propagate upwards
421 
422  // advance to parent and balance again
423  curr = parent_rw;
424  }
425 
426  // if y was red, this fixes the balance
427  TM_WRITE(curr->m_color, BLACK);
428 
429  // free storage associated with deleted node
430  TM_FREE(x_rw);
431 }
432 
433 
434 // returns black-height when balanced and -1 otherwise
436 {
437  if (!x)
438  return 0;
439  const RBNode* x_r(x);
440  int bh0 = blackHeight(x_r->m_child[0]);
441  int bh1 = blackHeight(x_r->m_child[1]);
442  if ((bh0 >= 0) && (bh1 == bh0))
443  return BLACK==x_r->m_color ? 1+bh0 : bh0;
444  else
445  return -1;
446 }
447 
448 // returns true when a red node has a red child
449 bool RBTree::redViolation(const RBNode* p_r, const RBNode* x)
450 {
451  if (!x)
452  return false;
453  const RBNode* x_r(x);
454  return ((RED == p_r->m_color && RED == x_r->m_color)
455  || (redViolation(x_r, x_r->m_child[0]))
456  || (redViolation(x_r, x_r->m_child[1])));
457 }
458 
459 // returns true when all nodes' parent fields point to their parents
460 bool RBTree::validParents(const RBNode* p, int xID, const RBNode* x)
461 {
462  if (!x)
463  return true;
464  const RBNode* x_r(x);
465  return ((x_r->m_parent == p)
466  && (x_r->m_ID == xID)
467  && (validParents(x, 0, x_r->m_child[0]))
468  && (validParents(x, 1, x_r->m_child[1])));
469 }
470 
471 // returns true when the tree is ordered
472 bool RBTree::inOrder(const RBNode* x, int lowerBound, int upperBound)
473 {
474  if (!x)
475  return true;
476  const RBNode* x_r(x);
477  return ((lowerBound <= x_r->m_val)
478  && (x_r->m_val <= upperBound)
479  && (inOrder(x_r->m_child[0], lowerBound, x_r->m_val - 1))
480  && (inOrder(x_r->m_child[1], x_r->m_val + 1, upperBound)));
481 }
482 
483 // build an empty tree
484 RBTree::RBTree() : sentinel(new RBNode()) { }
485 
486 // sanity check of the RBTree data structure
487 bool RBTree::isSane() const
488 {
489  const RBNode* sentinel_r(sentinel);
490  RBNode* root = sentinel_r->m_child[0];
491 
492  if (!root)
493  return true; // empty tree needs no checks
494 
495  const RBNode* root_r(root);
496  return ((BLACK == root_r->m_color) &&
497  (blackHeight(root) >= 0) &&
498  !(redViolation(sentinel_r, root)) &&
499  (validParents(sentinel, 0, root)) &&
500  (inOrder(root, INT_MIN, INT_MAX)));
501 }
502 
503 #endif // TREE_HPP__
RBNode * m_parent
Definition: Tree.hpp:26
#define TM_CALLABLE
Definition: cxxtm.hpp:32
Color m_color
Definition: Tree.hpp:24
TM_CALLABLE bool lookup(int val TM_ARG) const
Definition: Tree.hpp:72
#define TM_WRITE(x, y)
Definition: cxxtm.hpp:46
int m_ID
Definition: Tree.hpp:27
#define TM_ARG
Definition: cxxtm.hpp:40
static bool redViolation(const RBNode *p_r, const RBNode *x)
Definition: Tree.hpp:449
TM_CALLABLE void remove(int val TM_ARG)
Definition: Tree.hpp:214
static bool validParents(const RBNode *p, int xID, const RBNode *x)
Definition: Tree.hpp:460
RBNode * m_child[2]
Definition: Tree.hpp:28
static int blackHeight(const RBNode *x)
Definition: Tree.hpp:435
#define TM_READ(x)
Definition: cxxtm.hpp:45
TM_CALLABLE void modify(int val TM_ARG)
Definition: Tree.hpp:86
RBNode * sentinel
Definition: Tree.hpp:51
TM_CALLABLE void insert(int val TM_ARG)
Definition: Tree.hpp:95
Definition: Tree.hpp:17
#define TM_PARAM
Definition: cxxtm.hpp:42
int m_val
Definition: Tree.hpp:25
#define TM_ALLOC
Definition: library.hpp:294
bool isSane() const
Definition: Tree.hpp:487
Definition: Tree.hpp:19
Definition: Tree.hpp:22
struct @18 p
Color
Definition: Tree.hpp:19
RBNode(Color color=BLACK, long val=-1, RBNode *parent=NULL, long ID=0, RBNode *child0=NULL, RBNode *child1=NULL)
Definition: Tree.hpp:31
static bool inOrder(const RBNode *x, int lowerBound, int upperBound)
Definition: Tree.hpp:472
Definition: Tree.hpp:19
#define TM_FREE
Definition: library.hpp:295
RBTree()
Definition: Tree.hpp:484