L4Re - L4 Runtime Environment
avl_tree
Go to the documentation of this file.
1 // vi:set ft=cpp: -*- Mode: C++ -*-
6 /*
7  * (c) 2008-2009 Alexander Warg <warg@os.inf.tu-dresden.de>,
8  * Carsten Weinhold <weinhold@os.inf.tu-dresden.de>
9  * economic rights: Technische Universität Dresden (Germany)
10  *
11  * This file is part of TUD:OS and distributed under the terms of the
12  * GNU General Public License 2.
13  * Please see the COPYING-GPL-2 file for details.
14  *
15  * As a special exception, you may use this file as part of a free software
16  * library without restriction. Specifically, if other files instantiate
17  * templates or use macros or inline functions from this file, or you compile
18  * this file and link it with other files to produce an executable, this
19  * file does not by itself cause the resulting executable to be covered by
20  * the GNU General Public License. This exception does not however
21  * invalidate any other reasons why the executable file might be covered by
22  * the GNU General Public License.
23  */
24 
25 #pragma once
26 
27 #include "std_ops"
28 #include "pair"
29 
30 #include "bits/bst.h"
31 #include "bits/bst_iter.h"
32 
33 namespace cxx {
34 
39 {
40 private:
41  template< typename Node, typename Get_key, typename Compare >
42  friend class Avl_tree;
43 
45  typedef Bits::Direction Bal;
47  typedef Bits::Direction Dir;
48 
49  // We are a final BST node, hide interior.
56  Bal _balance;
58 
59 protected:
62 
63 private:
65  Avl_tree_node(Avl_tree_node const &o);
66 
68  void operator = (Avl_tree_node const &o)
69  {
70  Bits::Bst_node::operator = (o);
71  _balance = o._balance;
72  }
73 
75  explicit Avl_tree_node(bool) : Bits::Bst_node(true), _balance(Dir::N) {}
76 
78  static Bits::Bst_node *rotate2(Bst_node **t, Bal idir, Bal pre);
79 
81  bool balanced() const { return _balance == Bal::N; }
82 
84  Bal balance() const { return _balance; }
85 
87  void balance(Bal b) { _balance = b; }
88 };
89 
90 
107 template< typename Node, typename Get_key,
108  typename Compare = Lt_functor<typename Get_key::Key_type> >
109 class Avl_tree : public Bits::Bst<Node, Get_key, Compare>
110 {
111 private:
113 
115  using Bst::_head;
116 
118  using Bst::k;
119 
121  typedef typename Avl_tree_node::Bal Bal;
123  typedef typename Avl_tree_node::Bal Dir;
124 
126  Avl_tree(Avl_tree const &o);
127 
129  void operator = (Avl_tree const &o);
130 
131 public:
133  typedef typename Bst::Key_type Key_type;
134  typedef typename Bst::Key_param_type Key_param_type;
136 
137  // Grab iterator types from Bst
139  typedef typename Bst::Iterator Iterator;
144  typedef typename Bst::Rev_iterator Rev_iterator;
148 
156  Pair<Node *, bool> insert(Node *new_node);
157 
164  Node *remove(Key_param_type key);
168  Node *erase(Key_param_type key) { return remove(key); }
169 
171  Avl_tree() : Bst() {}
173  ~Avl_tree() noexcept
174  {
175  this->remove_all([](Node *){});
176  }
177 
178 #ifdef __DEBUG_L4_AVL
179  bool rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx);
180  bool rec_dump(bool print)
181  {
182  int dp=0;
183  return rec_dump(static_cast<Avl_tree_node *>(_head), 0, &dp, print, '+');
184  }
185 #endif
186 };
187 
188 
189 //----------------------------------------------------------------------------
190 /* IMPLEMENTATION: Bits::__Bst_iter_b */
191 
192 
193 inline
195 Avl_tree_node::rotate2(Bst_node **t, Bal idir, Bal pre)
196 {
197  typedef Bits::Bst_node N;
198  typedef Avl_tree_node A;
199  N *tmp[2] = { *t, N::next(*t, idir) };
200  *t = N::next(tmp[1], !idir);
201  A *n = static_cast<A*>(*t);
202 
203  N::next(tmp[0], idir, N::next(n, !idir));
204  N::next(tmp[1], !idir, N::next(n, idir));
205  N::next(n, !idir, tmp[0]);
206  N::next(n, idir, tmp[1]);
207 
208  n->balance(Bal::N);
209 
210  if (pre == Bal::N)
211  {
212  static_cast<A*>(tmp[0])->balance(Bal::N);
213  static_cast<A*>(tmp[1])->balance(Bal::N);
214  return 0;
215  }
216 
217  static_cast<A*>(tmp[pre != idir])->balance(!pre);
218  static_cast<A*>(tmp[pre == idir])->balance(Bal::N);
219 
220  return N::next(tmp[pre == idir], !pre);
221 }
222 
223 //----------------------------------------------------------------------------
224 /* Implementation of AVL Tree */
225 
226 /* Insert new _Node. */
227 template< typename Node, typename Get_key, class Compare>
230 {
231  typedef Avl_tree_node A;
232  typedef Bits::Bst_node N;
233  N **t = &_head; /* search variable */
234  N **s = &_head; /* node where rebalancing may occur */
235  Key_param_type new_key = Get_key::key_of(new_node);
236 
237  // search insertion point
238  for (N *p; (p = *t);)
239  {
240  Dir b = this->dir(new_key, p);
241  if (b == Dir::N)
242  return pair(static_cast<Node*>(p), false);
243 
244  if (!static_cast<A const *>(p)->balanced())
245  s = t;
246 
247  t = N::next_p(p, b);
248  }
249 
250  *static_cast<A*>(new_node) = A(true);
251  *t = new_node;
252 
253  N *n = *s;
254  A *a = static_cast<A*>(n);
255  if (!a->balanced())
256  {
257  A::Bal b(this->greater(new_key, n));
258  if (a->balance() != b)
259  {
260  // ok we got in balance the shorter subtree go higher
261  a->balance(Bal::N);
262  // propagate the new balance down to the new node
263  n = N::next(n, b);
264  }
265  else if (b == Bal(this->greater(new_key, N::next(n, b))))
266  {
267  // left-left or right-right case -> single rotation
268  A::rotate(s, b);
269  a->balance(Bal::N);
270  static_cast<A*>(*s)->balance(Bal::N);
271  n = N::next(*s, b);
272  }
273  else
274  {
275  // need a double rotation
276  n = N::next(N::next(n, b), !b);
277  n = A::rotate2(s, b, n == new_node ? Bal::N : Bal(this->greater(new_key, n)));
278  }
279  }
280 
281  for (A::Bal b; n && n != new_node; static_cast<A*>(n)->balance(b), n = N::next(n, b))
282  b = Bal(this->greater(new_key, n));
283 
284  return pair(new_node, true);
285 }
286 
287 
288 /* remove an element */
289 template< typename Node, typename Get_key, class Compare>
290 inline
292 {
293  typedef Avl_tree_node A;
294  typedef Bits::Bst_node N;
295  N **q = &_head; /* search variable */
296  N **s = &_head; /* last ('deepest') node on the search path to q
297  * with balance 0, at this place the rebalancing
298  * stops in any case */
299  N **t = 0;
300  Dir dir;
301 
302  // find target node and rebalancing entry
303  for (N *n; (n = *q); q = N::next_p(n, dir))
304  {
305  dir = Dir(this->greater(key, n));
306  if (dir == Dir::L && !this->greater(k(n), key))
307  /* found node */
308  t = q;
309 
310  if (!N::next(n, dir))
311  break;
312 
313  A const *a = static_cast<A const *>(n);
314  if (a->balanced() || (a->balance() == !dir && N::next<A>(n, !dir)->balanced()))
315  s = q;
316  }
317 
318  // nothing found
319  if (!t)
320  return 0;
321 
322  A *i = static_cast<A*>(*t);
323 
324  for (N *n; (n = *s); s = N::next_p(n, dir))
325  {
326  dir = Dir(this->greater(key, n));
327 
328  if (!N::next(n, dir))
329  break;
330 
331  A *a = static_cast<A*>(n);
332  // got one out of balance
333  if (a->balanced())
334  a->balance(!dir);
335  else if (a->balance() == dir)
336  a->balance(Bal::N);
337  else
338  {
339  // we need rotations to get in balance
340  Bal b = N::next<A>(n, !dir)->balance();
341  if (b == dir)
342  A::rotate2(s, !dir, N::next<A>(N::next(n, !dir), dir)->balance());
343  else
344  {
345  A::rotate(s, !dir);
346  if (b != Bal::N)
347  {
348  a->balance(Bal::N);
349  static_cast<A*>(*s)->balance(Bal::N);
350  }
351  else
352  {
353  a->balance(!dir);
354  static_cast<A*>(*s)->balance(dir);
355  }
356  }
357  if (n == i)
358  t = N::next_p(*s, dir);
359  }
360  }
361 
362  A *n = static_cast<A*>(*q);
363  *t = n;
364  *q = N::next(n, !dir);
365  *n = *i;
366 
367  return static_cast<Node*>(i);
368 }
369 
370 #ifdef __DEBUG_L4_AVL
371 template< typename Node, typename Get_key, class Compare>
372 bool Avl_tree<Node, Get_key, Compare>::rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx)
373 {
374  typedef Avl_tree_node A;
375 
376  if (!n)
377  return true;
378 
379  int dpx[2] = {depth,depth};
380  bool res = true;
381 
382  res = rec_dump(n->next<A>(Dir::R), depth + 1, dpx + 1, print, '/');
383 
384  if (print)
385  {
386  fprintf(stderr, "%2d: [%8p] b=%1d: ", depth, n, (int)n->balance().d);
387 
388  for (int i = 0; i < depth; ++i)
389  std::cerr << " ";
390 
391  std::cerr << pfx << (static_cast<Node*>(n)->item) << std::endl;
392  }
393 
394  res = res & rec_dump(n->next<A>(Dir::L), depth + 1, dpx, print, '\\');
395 
396  int b = dpx[1] - dpx[0];
397 
398  if (b < 0)
399  *dp = dpx[0];
400  else
401  *dp = dpx[1];
402 
403  Bal x = n->balance();
404  if ((b < -1 || b > 1) ||
405  (b == 0 && x != Bal::N) ||
406  (b == -1 && x != Bal::L) ||
407  (b == 1 && x != Bal::R))
408  {
409  if (print)
410  fprintf(stderr, "%2d: [%8p] b=%1d: balance error %d\n", depth, n, (int)n->balance().d, b);
411  return false;
412  }
413  return res;
414 }
415 #endif
416 
417 }
418 
Avl_tree_node()
Create an uninitialized node, this is what you should do.
Definition: avl_tree:61
Node * erase(Key_param_type key)
An alias for remove().
Definition: avl_tree:168
Our C++ library.
Definition: arith:22
__Bst_iter< _Node, _Node, Rev > Rev_iterator
Backward iterator.
Definition: bst.h:82
A generic AVL tree.
Definition: avl_tree:109
Bst_node()
Create uninitialized node.
Definition: bst_base.h:119
Node * remove(Key_param_type key)
Remove the node with key from the tree.
Definition: avl_tree:291
Go to the left child.
Definition: bst_base.h:44
Pair< Node *, bool > insert(Node *new_node)
Insert a new node into this AVL tree.
Definition: avl_tree:229
Bst::Const_rev_iterator Const_rev_iterator
Constant backward iterator for the tree.
Definition: avl_tree:146
__Bst_iter< _Node, _Node const, Fwd > Const_iterator
Constant forward iterator.
Definition: bst.h:80
BasicOStream cerr
Standard error stream.
__Bst_iter< _Node, _Node const, Rev > Const_rev_iterator
Constant backward.
Definition: bst.h:84
The direction to go in a binary search tree.
Definition: bst_base.h:39
Get_key::Key_type Key_type
The type of key values used to generate the total order of the elements.
Definition: bst.h:66
Bst::Rev_iterator Rev_iterator
Backward iterator for the tree.
Definition: avl_tree:144
static Bst_node * next(Bst_node const *p, Direction d)
Get next node in direction d.
Definition: bst_base.h:94
Bst::Const_iterator Const_iterator
Constant forward iterator for the tree.
Definition: avl_tree:142
static void rotate(Bst_node **t, Direction idir)
Rotate subtree t in the opposite direction of idir.
Definition: bst_base.h:127
Type_traits< Key_type >::Param_type Key_param_type
The type for key parameters.
Definition: bst.h:68
Avl_tree()
Create an empty AVL tree.
Definition: avl_tree:171
Pair implementation.
Generic comparator class that defaults to the less-than operator.
Definition: std_ops:29
Basic binary search tree (BST).
Definition: bst.h:40
AVL tree.
Basic type of a node in a binary search tree (BST).
Definition: bst_base.h:77
static Bst_node ** next_p(Bst_node *p, Direction d)
Get pointer to link in direction d.
Definition: bst_base.h:102
Bst::Iterator Iterator
Forward iterator for the tree.
Definition: avl_tree:140
Go to the right child.
Definition: bst_base.h:45
Node of an AVL tree.
Definition: avl_tree:38
__Bst_iter< Node, Node, Fwd > Iterator
Forward iterator.
Definition: bst.h:78
~Avl_tree() noexcept
Destroy the tree.
Definition: avl_tree:173
AVL tree.
Pair of two values.
Definition: pair:36