Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
tpl_rb_tree.H
1 
2 # ifndef TPL_RB_TREE_H
3 # define TPL_RB_TREE_H
4 
5 # include <ahFunction.H>
6 # include <tpl_arrayStack.H>
7 # include <tpl_binNodeUtils.H>
8 # include <rbNode.H>
9 
10 using namespace Aleph;
11 
12 namespace Aleph {
13 
33  template <template <typename> class NodeType, typename Key, class Compare>
35 {
36 public:
37 
38  typedef NodeType<Key> Node;
39 
40 private:
41 
42  Node head_node; // cabecera centinela
43  Node * head; // puntero a centinela
44  Node *& root;
45  FixedStack<Node*> rb_stack;
46  Compare & cmp;
47 
48  Node * search_and_stack_rb(const Key & key)
49  {
50  Node * p = root;
51  rb_stack.push(head);
52  do
53  {
54  rb_stack.push(p);
55  if (cmp(key, KEY(p)))
56  p = LLINK(p);
57  else if (cmp(KEY(p), key))
58  p = RLINK(p);
59  else
60  return p;
61  }
62  while (p != Node::NullPtr);
63 
64  return rb_stack.top();
65  }
66 
67  Node * search_dup_and_stack_rb(const Key & key)
68  {
69  Node * p = root;
70  rb_stack.push(head);
71  do
72  {
73  rb_stack.push(p);
74  if (cmp(key, KEY(p)))
75  p = LLINK(p);
76  else
77  p = RLINK(p);
78  }
79  while (p != Node::NullPtr);
80 
81  return rb_stack.top();
82  }
83 
84  void fix_red_condition(Node * p)
85  {
86  I(COLOR(p) == RED);
87 
88  while (p != root)
89  {
90  Node * pp = rb_stack.pop(); // padre de p
91  if (COLOR(pp) == BLACK) // ¿padre de p negro?
92  break; // sí ==> no hay rojos consecutivos ==> terminar
93 
94  if (root == pp) // ¿p es hijo directo de la raíz?
95  { // sí ==> colorear raíz de negro y terminar
96  COLOR(root) = BLACK;
97  break;
98  }
99 
100  Node * ppp = rb_stack.pop(); // abuelo de p
101  Node * spp = LLINK(ppp) == pp ? RLINK(ppp) : LLINK(ppp); // tío
102  if (COLOR(spp) == RED) // ¿tío de p rojo?
103  { // intercambiar colores entre los niveles
104  COLOR(ppp) = RED;
105  COLOR(pp) = BLACK;
106  COLOR(spp) = BLACK;
107  p = ppp;
108  continue; // ir próximo ancestro, verificar violaciones
109  }
110 
111  Node * pppp = rb_stack.pop(); // bisabuelo de p
112  if (LLINK(pp) == p and LLINK(ppp) == pp)
113  {
114  rotate_to_right(ppp, pppp);
115  COLOR(pp) = BLACK;
116  }
117  else if (RLINK(pp) == p and RLINK(ppp) == pp)
118  {
119  rotate_to_left(ppp, pppp);
120  COLOR(pp) = BLACK;
121  }
122  else
123  {
124  if (RLINK(pp) == p)
125  {
126  rotate_to_left(pp, ppp);
127  rotate_to_right(ppp, pppp);
128  }
129  else
130  {
131  rotate_to_right(pp, ppp);
132  rotate_to_left(ppp, pppp);
133  }
134  COLOR(p) = BLACK;
135  }
136 
137  COLOR(ppp) = RED;
138  break; // árbol es rojo-negro ==> terminar
139  }
140 
141  rb_stack.empty();
142  }
143 
144  void find_succ_and_swap(Node * p, Node *& pp)
145  {
146  Node *& ref_rb_stack = rb_stack.top();
147 
148  /* Find successor while updating rb_stack */
149  Node * fSucc = p; // successor's parent
150  Node * succ = RLINK(p); // Searching starts from p's right child
151  rb_stack.push(succ);
152 
153  while (LLINK(succ) != Node::NullPtr) // go down to leftmost
154  {
155  fSucc = succ;
156  succ = LLINK(succ);
157  rb_stack.push(succ);
158  }
159 
160  ref_rb_stack = succ; /* swap old top with current top */
161  rb_stack.top() = p;
162 
163  if (LLINK(pp) == p) /* Setting of parent of p to new child(succ) */
164  LLINK(pp) = succ;
165  else
166  RLINK(pp) = succ;
167 
168  LLINK(succ) = LLINK(p); /* Swaps left branches */
169  LLINK(p) = Node::NullPtr;
170 
171  if (RLINK(p) == succ) /* For right branches there are two cases */
172  { /* successor is just right child of p */
173  RLINK(p) = RLINK(succ);
174  RLINK(succ) = p;
175  pp = succ;
176  }
177  else
178  { /* Successor is leftmost node descending from right child of p */
179  Node *succr = RLINK(succ);
180  RLINK(succ) = RLINK(p);
181  LLINK(fSucc) = p;
182  RLINK(p) = succr;
183  pp = fSucc;
184  }
185 
186  std::swap(COLOR(succ), COLOR(p));
187  }
188 
189  void fix_black_condition(Node * p)
190  {
191  if (COLOR(p) == RED) // ¿p es rojo?
192  { // sí ==> lo pintamos de negro y terminamos
193  COLOR(p) = BLACK; // esto compensa el déficit
194  return;
195  }
196 
197  Node * pp = rb_stack.popn(2); // padre de p
198  while (p != root)
199  {
200  I(LLINK(pp) == p or RLINK(pp) == p);
201  I(LLINK(rb_stack.top()) == pp or RLINK(rb_stack.top()) == pp);
202 
203  Node * sp = LLINK(pp) == p ? RLINK(pp) : LLINK(pp); // hermano p
204  if (COLOR(sp) == RED) // ¿hermano de p es rojo?
205  {
206  Node *& ppp = rb_stack.top(); // abuelo de p
207 
208  if (LLINK(pp) == p)
209  {
210  sp = LLINK(sp);
211  ppp = rotate_to_left(pp, ppp);
212  }
213  else
214  {
215  sp = RLINK(sp);
216  ppp = rotate_to_right(pp, ppp);
217  }
218 
219  COLOR(ppp) = BLACK;
220  COLOR(pp) = RED;
221  }
222 
223  Node * np, * snp; // sobrinos de nodo p
224  if (LLINK(pp) == p) // ¿p es hijo izquierdo?
225  { // sí ==> que sp es hijo derechos
226  np = RLINK(sp);
227  snp = LLINK(sp);
228  }
229  else
230  {
231  np = LLINK(sp);
232  snp = RLINK(sp);
233  }
234 
235  if (COLOR(np) == RED) // ¿np es rojo?
236  {
237  Node * ppp = rb_stack.top();
238 
239  if (RLINK(sp) == np)
240  rotate_to_left(pp, ppp);
241  else
242  rotate_to_right(pp, ppp);
243 
244  COLOR(sp) = COLOR(pp);
245  COLOR(pp) = BLACK;
246  COLOR(np) = BLACK;
247 
248  return;
249  }
250 
251  if (COLOR(snp) == RED) // ¿snp es rojo?
252  {
253  Node * ppp = rb_stack.top();
254 
255  if (LLINK(sp) == snp)
256  {
257  rotate_to_right(sp, pp);
258  rotate_to_left(pp, ppp);
259  }
260  else
261  {
262  rotate_to_left(sp, pp);
263  rotate_to_right(pp, ppp);
264  }
265 
266  COLOR(snp) = COLOR(pp);
267  COLOR(pp) = BLACK;;
268 
269  return;
270  }
271 
272  if (COLOR(pp) == RED) // ¿pp es rojo?
273  {
274  COLOR(pp) = BLACK;
275  COLOR(sp) = RED;;
276  return;
277  }
278 
279  // no hay nodo rojo en las adyacencias de p ==> desplazar el
280  // déficit hacia pp y repetir la iteración
281  COLOR(sp) = RED;
282  p = pp;
283  pp = rb_stack.pop();
284  }
285  }
286 
287 
288 public:
289 
291  typedef Key key_type;
292 
294  Compare & key_comp() { return cmp; }
295 
297  Compare & get_compare() { return key_comp(); }
298 
300  Gen_Rb_Tree(Compare && __cmp)
301  : rb_stack(Node::MaxHeight), head(&head_node),
302  root(head_node.getR()), cmp(__cmp)
303  {
304  /* empty */
305  }
306 
307  Gen_Rb_Tree(Compare & __cmp)
308  : rb_stack(Node::MaxHeight), head(&head_node),
309  root(head_node.getR()), cmp(__cmp)
310  {
311  /* empty */
312  }
313 
319  void swap (Gen_Rb_Tree & tree)
320  {
321  std::swap(root, tree.root);
322  std::swap(cmp, tree.cmp);
323  }
324 
326  virtual ~Gen_Rb_Tree() { /* empty */ }
327 
331  Node * search(const Key & key)
332  {
333  Node * retVal = Aleph::searchInBinTree <Node, Compare> (root, key, cmp);
334  return retVal == Node::NullPtr ? NULL : retVal;
335  }
336 
338  Node *& getRoot() { return root; }
343  Node * insert(Node * p)
344  {
345  I(COLOR(p) == RED);
346 
347  if (root == Node::NullPtr)
348  return root = p; // inserción en árbol vacío
349 
350  Node * q = search_and_stack_rb(KEY(p));
351  if (cmp(KEY(p), KEY(q)))
352  LLINK(q) = p;
353  else if (cmp(KEY(q), KEY(p)))
354  RLINK(q) = p;
355  else
356  {
357  rb_stack.empty();
358  return NULL; // clave duplicada
359  }
360  fix_red_condition(p);
361 
362  return p;
363  }
364 
379  Node * search_or_insert(Node * p)
380  {
381  I(COLOR(p) == RED);
382 
383  if (root == Node::NullPtr)
384  return root = p; // inserción en árbol vacío
385 
386  Node * q = search_and_stack_rb(KEY(p));
387  if (cmp(KEY(p), KEY(q)))
388  LLINK(q) = p;
389  else if (cmp(KEY(q), KEY(p)))
390  RLINK(q) = p;
391  else
392  {
393  rb_stack.empty();
394  return q; // clave duplicada
395  }
396  fix_red_condition(p);
397 
398  return p;
399  }
400 
405  Node * insert_dup(Node * p)
406  {
407  I(COLOR(p) == RED);
408 
409  if (root == Node::NullPtr)
410  return root = p; // inserción en árbol vacío
411 
412  Node * q = search_dup_and_stack_rb(KEY(p));
413  if (cmp(KEY(p), KEY(q)))
414  LLINK(q) = p;
415  else
416  RLINK(q) = p;
417 
418  fix_red_condition(p);
419 
420  return p;
421  }
422 
423  bool verify() { return is_red_black_tree(root) ; }
424 
429  Node* remove(const Key & key)
430  {
431  if (root == Node::NullPtr)
432  return NULL;
433 
434  Node * q = search_and_stack_rb(key);
435  if (no_equals<Key, Compare> (KEY(q), key, cmp)) // ¿clave no encontrada?
436  {
437  rb_stack.empty();
438  return NULL;
439  }
440 
441  Node * pq = rb_stack.top(1); // padre de 1
442  Node * p; // hijo de q luego de que éste ha sido eliminado
443  while (true) // eliminación clásica árbol binario de búsqueda
444  {
445  if (LLINK(q) == Node::NullPtr)
446  {
447  if (LLINK(pq) == q)
448  p = LLINK(pq) = RLINK(q);
449  else
450  p = RLINK(pq) = RLINK(q);
451 
452  break; // goto end;
453  }
454 
455  if (RLINK(q) == Node::NullPtr)
456  {
457  if (LLINK(pq) == q)
458  p = LLINK(pq) = LLINK(q);
459  else
460  p = RLINK(pq) = LLINK(q);
461 
462  break; // goto end;
463  }
464 
465  find_succ_and_swap(q, pq);
466  }
467 
468  if (COLOR(q) == BLACK) // ¿se eliminó un nodo negro?
469  fix_black_condition(p);
470 
471  q->reset();
472  rb_stack.empty();
473 
474  return q;
475  }
476 };
491  template <typename Key, class Compare = Aleph::less<Key>>
492 struct Rb_Tree : public Gen_Rb_Tree<RbNode, Key, Compare>
493 {
494 public:
495 
496  Rb_Tree(Compare && cmp = Compare())
497  : Gen_Rb_Tree<RbNode, Key, Compare> (std::move(cmp))
498  {
499  // empty
500  }
501 
502  Rb_Tree(Compare & cmp)
504  {
505  // empty
506  }
507 };
508 
524  template <typename Key, class Compare = Aleph::less<Key>>
525 struct Rb_Tree_Vtl : public Gen_Rb_Tree<RbNodeVtl, Key, Compare>
526 {
527 public:
528 
529  Rb_Tree_Vtl(Compare && cmp = Compare())
530  : Gen_Rb_Tree<RbNodeVtl, Key, Compare> (std::move(cmp))
531  {
532  // empty
533  }
534 
535  Rb_Tree_Vtl(Compare & cmp)
537  {
538  // empty
539  }
540 };
541 
542 } // end namespace Aleph
543 
544 # endif // TPL_RB_TREE_H
545 
Node * rotate_to_left(Node *p)
Definition: tpl_binNodeUtils.H:2422
void swap(Gen_Rb_Tree &tree)
Definition: tpl_rb_tree.H:319
Key key_type
El tipo de clave que contiene el nodo.
Definition: tpl_rb_tree.H:291
#define LLINK(p)
Definition: tpl_binNode.H:196
Node *& getRoot()
Obtiene un puntero a la raíz del árbol.
Definition: tpl_rb_tree.H:338
Definition: tpl_rb_tree.H:492
Definition: tpl_rb_tree.H:525
#define RLINK(p)
Definition: tpl_binNode.H:201
Gen_Rb_Tree(Compare &&__cmp)
Instancia un árbol rojo-negro.
Definition: tpl_rb_tree.H:300
T pop()
Definition: tpl_arrayStack.H:353
Definition: tpl_rb_tree.H:34
T & push(const T &data)
Definition: tpl_arrayStack.H:312
Node * search_or_insert(Node *p)
Definition: tpl_rb_tree.H:379
T popn(const int &n)
Definition: tpl_arrayStack.H:369
Node * rotate_to_right(Node *p)
Definition: tpl_binNodeUtils.H:2375
Compare & get_compare()
Definition: tpl_rb_tree.H:297
Compare & key_comp()
Retorna una referencia al criterio de comparación.
Definition: tpl_rb_tree.H:294
Node * insert_dup(Node *p)
Definition: tpl_rb_tree.H:405
T & top()
retorna una referencia al elemento situado en el tope de la pila.
Definition: tpl_arrayStack.H:378
virtual ~Gen_Rb_Tree()
Destruye un árbol rojo-negro.
Definition: tpl_rb_tree.H:326
#define KEY(p)
Definition: tpl_binNode.H:206
Node * search(const Key &key)
Definition: tpl_rb_tree.H:331
Node * insert(Node *p)
Definition: tpl_rb_tree.H:343
void empty()
Vacía todos los elementos de la pila.
Definition: tpl_arrayStack.H:416

Leandro Rabindranath León