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_avl.H
1 
2 # ifndef TPL_AVL_H
3 # define TPL_AVL_H
4 
5 # include <algorithm>
6 # include <ahFunction.H>
7 # include <tpl_arrayStack.H>
8 # include <avlNode.H>
9 # include <tpl_binNodeUtils.H>
10 
11 using namespace Aleph;
12 
13 namespace Aleph {
14 
34  template <template <typename> class NodeType, typename Key, class Compare>
36 {
37 public:
38 
39  typedef NodeType<Key> Node;
40 
41 private:
42 
43  FixedStack<Node *> avl_stack;
44  Node head_node;
45  Node * head_ptr;
46  Node *& root;
47  Compare & cmp;
48 
49  bool avl_stack_empty() { return avl_stack.top() == head_ptr; }
50 
51  void clean_avl_stack() { avl_stack.popn (avl_stack.size() - 1); }
52 
53  Node * search_and_stack_avl(const Key & key)
54  {
55  I(avl_stack_empty());
56 
57  Node * p = root;
58  do // desciende en búsqueda de key y empila camino de búsqueda
59  {
60  avl_stack.push(p);
61  if (cmp(key, KEY(p))) // ¿key < KEY(p)?
62  p = LLINK(p);
63  else if (cmp(KEY(p), key)) // ¿key > KEY(p)?
64  p = RLINK(p);
65  else
66  return p; // clave duplicada
67  }
68  while (p != Node::NullPtr);
69 
70  return avl_stack.top();
71  }
72 
73  Node * search_dup_and_stack_avl(const Key & key)
74  {
75  I(avl_stack_empty());
76 
77  Node * p = root;
78  do // desciende en búsqueda de key y empila camino de búsqueda
79  {
80  avl_stack.push(p);
81  if (cmp(key, KEY(p))) // ¿key < KEY(p)?
82  p = LLINK(p);
83  else // key >= KEY(p)
84  p = RLINK(p);
85  }
86  while (p != Node::NullPtr);
87 
88  return avl_stack.top();
89  }
90 
91  static Node * rotateLeft(Node * p)
92  {
93  I(DIFF(p) == 2);
94  I(RLINK(p) != Node::NullPtr);
95 
96  Node * q = RLINK(p);
97  RLINK(p) = LLINK(q);
98  LLINK(q) = p;
99 
100  if (DIFF(q) == 0) // ajuste de los factores de equilibrio
101  { // este caso ocurre durante la eliminación
102  DIFF(q) = -1;
103  DIFF(p) = 1;
104  }
105  else
106  DIFF(q) = DIFF(p) = 0;
107 
108  return q;
109  }
110 
111  static Node * rotateRight(Node * p)
112  {
113  I(DIFF(p) == -2);
114  I(LLINK(p) != Node::NullPtr);
115 
116  Node * q = LLINK(p);
117  LLINK(p) = RLINK(q);
118  RLINK(q) = p;
119 
120  if (DIFF(q) == 0) // ajuste de los factores de equilibrio
121  { // este caso ocurre durante la eliminación
122  DIFF(q) = 1;
123  DIFF(p) = -1;
124  }
125  else
126  DIFF(q) = DIFF(p) = 0;
127 
128  return q;
129  }
130 
131  static Node * doubleRotateLeft(Node * p)
132  {
133  I(DIFF(p) == 2 or DIFF(p) == -2);
134  I(RLINK(p) != Node::NullPtr and LLINK(RLINK(p)) != Node::NullPtr);
135 
136  Node * q = RLINK(p);
137  Node * r = LLINK(q);
138  RLINK(p) = LLINK(r);
139  LLINK(q) = RLINK(r);
140  LLINK(r) = p;
141  RLINK(r) = q;
142 
143  unsigned char b; // altura lógica de hijo izq de r
144  unsigned char c; // altura lógica de hijo der de r
145 
146  // Determinación de alturas lógicas de p, q y r
147  if (DIFF(r) == 1) // ==> c > b ==> c-b == 1
148  {
149  c = 1;
150  b = 0;
151  }
152  else if (DIFF(r) == -1) // ==> c < b ==> c-b = -1
153  {
154  c = 0;
155  b = 1;
156  }
157  else
158  c = b = 1;
159 
160  // ajuste de factores de equilibrio
161  DIFF(r) = 0;
162  DIFF(p) = b - 1; // altura lógica de hijo izq de p es 1
163  DIFF(q) = 1 - c; // altura lógica de hijo der de q es 1
164 
165  return r;
166  }
167 
168  static Node * doubleRotateRight(Node * p)
169  {
170  I(DIFF(p) == 2 or DIFF(p) == -2);
171  I(LLINK(p) != Node::NullPtr and RLINK(LLINK(p)) != Node::NullPtr);
172 
173  Node * q = LLINK(p);
174  Node * r = RLINK(q);
175  LLINK(p) = RLINK(r);
176  RLINK(q) = LLINK(r);
177  RLINK(r) = p;
178  LLINK(r) = q;
179 
180  unsigned char b; // altura lógica de hijo izq de r
181  unsigned char c; // altura lógica de hijo der de r
182 
183  // determinación de alturas lógicas de hijos de p, q y r
184  if (DIFF(r) == 1) // ==> c > b ==> c-b == 1
185  {
186  c = 1;
187  b = 0;
188  }
189  else if (DIFF(r) == -1) // ==> c < b ==> c-b == -1
190  {
191  c = 0;
192  b = 1;
193  }
194  else
195  c = b = 1;
196 
197  // ajuste de factores de equilibrio
198  DIFF(r) = 0;
199  DIFF(p) = 1 - c; // altura lógica de hijo der de p es 1
200  DIFF(q) = b - 1; // altura lógica de hijo izq de p es 1
201 
202  return r;
203  }
204 
205  enum Rotation_Type
206  { ROTATE_LEFT, ROTATE_RIGHT, DOUBLE_ROTATE_LEFT, DOUBLE_ROTATE_RIGHT };
207 
208  static Rotation_Type rotation_type(Node * p)
209  {
210  I(DIFF(p) == 2 or DIFF(p) == -2);
211 
212  Node * pc; // guarda hijo de p
213  if (DIFF(p) == 2) // hacia la izquierda
214  {
215  pc = RLINK(p);
216  if (DIFF(pc) == 1 or DIFF(pc) == 0)
217  return ROTATE_LEFT;
218 
219  return DOUBLE_ROTATE_LEFT;
220  }
221 
222  pc = LLINK(p);
223  if (DIFF(pc) == -1 or DIFF(pc) == 0)
224  return ROTATE_RIGHT;
225 
226  return DOUBLE_ROTATE_RIGHT;
227  }
228 
229  static Node * restore_avl(Node * p, Node * pp)
230  {
231  I(LLINK(pp) == p or RLINK(pp) == p);
232  I(DIFF(p) == -2 or DIFF(p) == 2);
233 
234  Node ** link = LLINK(pp) == p ? &LLINK(pp) : &RLINK(pp);
235  switch (rotation_type(p))
236  {
237  case ROTATE_LEFT: return *link = rotateLeft(p);
238  case ROTATE_RIGHT: return *link = rotateRight(p);
239  case DOUBLE_ROTATE_LEFT: return *link = doubleRotateLeft(p);
240  case DOUBLE_ROTATE_RIGHT: return *link = doubleRotateRight(p);
241 
242  default:
243  ERROR("Invalid rotation type");
244  break;
245  }
246 
247  return NULL;
248  }
249 
250  void restore_avl_after_insertion(Node * p) // ERROR const Key & key)
251  {
252  Node * pp = avl_stack.pop(); // padre del nodo insertado
253  if (LLINK(pp) == p) // ajuste el factor del padre del nodo insertado OJO
254  DIFF(pp)--;
255  else
256  DIFF(pp)++;
257 
258  if (DIFF(pp) == 0)
259  { // en este caso, altura del ascendiente de pp no aumenta
260  clean_avl_stack();
261  return;
262  }
263 
264  if (avl_stack_empty())
265  return; // pp es raíz
266 
267  Node *gpp; // padre de pp
268  do // buscar nodo con factor igual a 0
269  {
270  gpp = avl_stack.pop();
271  // actualizar factores de equilibrio
272  if (LLINK(gpp) == pp) // ERROR if (Compare () (key, KEY(gpp)))
273  DIFF(gpp)--;
274  else
275  DIFF(gpp)++;
276 
277  if (DIFF(gpp) == 0)
278  break; // no se necesita reajuste
279  else if (DIFF(gpp) == -2 or DIFF(gpp) == 2)// ¿es AVL?
280  { // sí ==> se requiere reajuste
281  Node *ggpp = avl_stack.pop();
282  restore_avl(gpp, ggpp);
283  break;
284  }
285 
286  pp = gpp; // ERROR; añadir
287  }
288  while (not avl_stack_empty());
289 
290  clean_avl_stack();
291  }
292 
293  Node * swapWithSuccessor(Node * p, Node *& pp)
294  { // Referencia al tope de la pila, pues p será intercambiado con
295  // sucesor y la posición en la pila la ocupará el sucesor de p
296  Node *& ref_to_stack_top = avl_stack.top();
297 
298  Node *fSucc = p; // padre del sucesor
299  Node *succ = RLINK(p); // búsqueda comienza desde RLINK(p)
300 
301  avl_stack.push(succ);
302 
303  // encuentre el sucesor a la vez que actualiza la pila
304  while (LLINK(succ) != Node::NullPtr) // descender lo más a la izq
305  {
306  fSucc = succ;
307  succ = LLINK(succ);
308  avl_stack.push(succ);
309  }
310 
311  // actualice antigua entrada de pila ocupada por p. Equivale
312  // a intercambiar antiguo tope (antes de buscar suc) con actual
313  ref_to_stack_top = succ;
314  avl_stack.top() = p;
315  if (LLINK(pp) == p) // actualice el nuevo hijo de pp (sucesor)
316  LLINK(pp) = succ;
317  else
318  RLINK(pp) = succ;
319 
320  LLINK(succ) = LLINK(p); // intercambie las ramas izquierdas
321  LLINK(p) = Node::NullPtr;
322  if (RLINK(p) == succ) // actualice ramas derechas
323  { // sucesor es exactamente el hijo derecho de p
324  RLINK(p) = RLINK(succ);
325  RLINK(succ) = p;
326  pp = succ;
327  }
328  else
329  { // sucesor es el descendiente más a la izquierda de RLINK(p)
330  Node *succr = RLINK(succ);
331  RLINK(succ) = RLINK(p);
332  LLINK(fSucc) = p;
333  RLINK(p) = succr;
334  pp = fSucc;
335  }
336 
337  DIFF(succ) = DIFF(p); // intercambie factores de equilibrio
338 
339  return succ;
340  }
341 
342  void restore_avl_after_deletion(bool left_deficit) // ERROR const Key & key)
343  {
344  Node * pp = avl_stack.top(1); // padre de p
345  Node * ppp = avl_stack.popn(3); // elimina de pila p, padre y abuelo
346  while (true)
347  { // actualice factores de equilibrio
348  if (left_deficit) // ERROR Compare () (key, KEY(pp)))
349  DIFF(pp)++;
350  else
351  DIFF(pp)--;
352 
353  if (DIFF(pp) == -2 or DIFF(pp) == 2) // ¿es válido?
354  pp = restore_avl(pp, ppp); // no!
355 
356  if (DIFF(pp) != 0 or pp == root)
357  break; // altura global de árbol no ha cambiado ==> terminar
358 
359  left_deficit = LLINK(ppp) == pp;
360  pp = ppp; // avance al próximo ascendiente
361  ppp = avl_stack.pop();
362  }
363 
364  clean_avl_stack();
365  }
366 
367 public:
368 
370  typedef Key key_type;
371 
373  Compare & key_comp() { return cmp; }
374 
376  Compare & get_compare() { return key_comp(); }
377 
379  Gen_Avl_Tree(Compare && __cmp)
380  : avl_stack(Node::MaxHeight), head_ptr(&head_node),
381  root(RLINK (head_ptr)), cmp(__cmp)
382  {
383  avl_stack.push(head_ptr);
384  }
385 
386  Gen_Avl_Tree(Compare & __cmp)
387  : avl_stack(Node::MaxHeight), head_ptr(&head_node),
388  root(RLINK (head_ptr)), cmp(__cmp)
389  {
390  avl_stack.push(head_ptr);
391  }
392 
398  void swap(Gen_Avl_Tree & tree)
399  {
400  std::swap(root, tree.root);
401  std::swap(cmp, tree.cmp);
402  }
403 
405  virtual ~Gen_Avl_Tree() { I(avl_stack_empty()); }
406 
408  Node *& getRoot() { return root; }
409 
412  Node * search(const Key & key) const
413  {
414  return searchInBinTree <Node, Compare> (root, key, cmp);
415  }
416 
420  Node * insert(Node * p)
421  {
422  if (root == Node::NullPtr)
423  return root = p;
424 
425  Node *pp = search_and_stack_avl(KEY(p));
426  if (cmp (KEY(p), KEY(pp)))
427  LLINK (pp) = p;
428  else if (cmp (KEY(pp), KEY(p)))
429  RLINK(pp) = p;
430  else
431  { // clave duplicada
432  clean_avl_stack();
433  return NULL;
434  }
435 
436  restore_avl_after_insertion(p);
437 
438  return p;
439  }
440 
456  {
457  if (root == Node::NullPtr)
458  return root = p;
459 
460  Node *pp = search_and_stack_avl(KEY(p));
461  if (cmp (KEY(p), KEY(pp)))
462  LLINK (pp) = p;
463  else if (cmp (KEY(pp), KEY(p)))
464  RLINK(pp) = p;
465  else
466  { // clave duplicada
467  clean_avl_stack();
468  return pp;
469  }
470 
471  restore_avl_after_insertion(p);
472 
473  return p;
474  }
475 
479  {
480  if (root == Node::NullPtr)
481  return root = p;
482 
483  Node *pp = search_dup_and_stack_avl(KEY(p));
484  if (cmp (KEY(p), KEY(pp)))
485  LLINK (pp) = p;
486  else
487  RLINK(pp) = p;
488 
489  restore_avl_after_insertion(p);
490 
491  return p;
492  }
493 
497  Node * remove(const Key & key)
498  {
499  if (root == Node::NullPtr)
500  return NULL;
501 
502  Node * p = search_and_stack_avl(key);
503  if (no_equals<Key, Compare> (KEY(p), key, cmp))
504  { // clave no fue encontrada
505  clean_avl_stack();
506  return NULL;
507  }
508 
509  Node * pp = avl_stack.top(1); // obtener padre de p
510  bool left_deficit; // ERROR Key removed_key = KEY(p);
511  while (true)
512  {
513  left_deficit = LLINK(pp) == p;
514  if (LLINK(p) == Node::NullPtr) // ¿incompleto por la izquierda?
515  { // Sí, ate a pp el hijo de p
516  if (LLINK(pp) == p)
517  LLINK(pp) = RLINK(p);
518  else
519  RLINK(pp) = RLINK(p);
520  break;
521  }
522 
523  if (RLINK(p) == Node::NullPtr) // ¿incompleto por la izquierda?
524  { // Sí, ate a pp el hijo de p
525  if (LLINK(pp) == p)
526  LLINK(pp) = LLINK(p);
527  else
528  RLINK(pp) = LLINK(p);
529  break;
530  }
531 
532  // aquí p es un nodo completo ==> intercambiar por sucesor
533  swapWithSuccessor(p, pp);
534  // removed_key = KEY(succ); // ERROR eliminar
535  }
536 
537  p->reset();
538 
539  if (pp == head_ptr) // verifique si se eliminó la raíz
540  { // factores quedan inalterados ==> no se viola condición AVL
541  clean_avl_stack();
542  return p;
543  }
544 
545  restore_avl_after_deletion(left_deficit); // ERROR
546 
547  return p;
548  }
549 
550  bool verify()
551  {
552  return is_avl(root);
553  }
554 
555 };
572  template <typename Key, class Compare = Aleph::less<Key>>
573 class Avl_Tree : public Gen_Avl_Tree<AvlNode, Key, Compare>
574 {
575 public:
576 
577  Avl_Tree(Compare && cmp = Compare())
578  : Gen_Avl_Tree<AvlNode, Key, Compare> (std::move(cmp))
579  {
580  // empty
581  }
582 
583  Avl_Tree(Compare & cmp)
585  {
586  // empty
587  }
588 };
589 
606  template <typename Key, class Compare = Aleph::less<Key>>
607 class Avl_Tree_Vtl : public Gen_Avl_Tree<AvlNodeVtl, Key, Compare>
608 {
609 public:
610 
611  Avl_Tree_Vtl(Compare && cmp = Compare())
612  : Gen_Avl_Tree<AvlNodeVtl, Key, Compare> (std::move(cmp))
613  {
614  // empty
615  }
616 
617  Avl_Tree_Vtl(Compare & cmp)
619  {
620  // empty
621  }
622 };
623 
624 } // end namespace Aleph
625 # endif // TPL_AVL_H
626 
#define LLINK(p)
Definition: tpl_binNode.H:196
Node * search(const Key &key) const
Definition: tpl_avl.H:412
#define RLINK(p)
Definition: tpl_binNode.H:201
Node * insert(Node *p)
Definition: tpl_avl.H:420
virtual ~Gen_Avl_Tree()
Destruye un árbol AVL genérico.
Definition: tpl_avl.H:405
T pop()
Definition: tpl_arrayStack.H:353
Compare & key_comp()
Retorna una referencia al criterio de comparación.
Definition: tpl_avl.H:373
T & push(const T &data)
Definition: tpl_arrayStack.H:312
const size_t & size() const
Retorna el número de elementos que contiene la pila.
Definition: tpl_arrayStack.H:419
T popn(const int &n)
Definition: tpl_arrayStack.H:369
Node * insert_dup(Node *p)
Definition: tpl_avl.H:478
Definition: tpl_avl.H:607
Node *& getRoot()
Obtiene un puntero a la raíz del árbol.
Definition: tpl_avl.H:408
Key key_type
El tipo de clave que contiene el nodo.
Definition: tpl_avl.H:370
Node * search_or_insert(Node *p)
Definition: tpl_avl.H:455
void swap(Gen_Avl_Tree &tree)
Definition: tpl_avl.H:398
Definition: tpl_avl.H:35
Gen_Avl_Tree(Compare &&__cmp)
Instancia un árbol AVL genérico.
Definition: tpl_avl.H:379
Definition: tpl_avl.H:573
T & top()
retorna una referencia al elemento situado en el tope de la pila.
Definition: tpl_arrayStack.H:378
#define KEY(p)
Definition: tpl_binNode.H:206
Compare & get_compare()
Definition: tpl_avl.H:376

Leandro Rabindranath León