]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/cxx/lib/tl/include/avl_tree
update
[l4.git] / l4 / pkg / cxx / lib / tl / include / avl_tree
index 60ccb6bf62ec5b6a8b7b7d0a3ea3bd3e5d14b151..eadec40ec88d9b6b664d3105f150140c0639d656 100644 (file)
 
 #pragma once
 
-#include <l4/cxx/std_ops>
-#include <l4/cxx/pair>
-#include <l4/cxx/type_traits>
+#include "std_ops"
+#include "pair"
 
-namespace cxx {
-
-/**
- * \internal
- * \ingroup cxx_api
- * \brief Generic iterator for the AVL-tree based set.
- * \param Cmp the type of the comparison functor.
- * \param Node the type of a node.
- * \param Node_op the type used to determine the direction of the iterator.
- */
-template< typename Node, typename Node_op >
-class __Avl_tree_iter_b
-{
-protected:
-  Node const *_n;   ///< Current node
-  Node const *_r;   ///< Root node of current subtree
-
-  /// Create an invalid iterator, used as end marker.
-  __Avl_tree_iter_b() : _n(0), _r(0) {}
-
-  /**
-   * \brief Create an iterator for the given AVL tree.
-   * \param t the root node of the tree to iterate.
-   * \param cmp the comparison functor for tree elements.
-   */
-  __Avl_tree_iter_b(Node const *t)
-    : _n(t), _r(_n)
-  { _downmost(); }
-
-  __Avl_tree_iter_b(Node const *t, Node const *r)
-    : _n(t), _r(r)
-  {}
-
-  /// traverse the subtree down to the leftmost/rightmost leave.
-  inline void _downmost();
+#include "bits/bst.h"
+#include "bits/bst_iter.h"
 
-  /// Increment to the next element.
-  inline void inc();
-
-public:
-  /// Check two iterators for equality.
-  bool operator == (__Avl_tree_iter_b const &o) const { return _n == o._n; }
-  /// Check two iterators for non equality.
-  bool operator != (__Avl_tree_iter_b const &o) const { return _n != o._n; }
-};
+namespace cxx {
 
 /**
- * \internal
- * \ingroup cxx_api
- * \brief Generic iterator for the AVL-tree based set.
- * \param Node the type of a node.
- * \param Node_type the type of the node to return stored in a node.
- * \param Node_op the type used to determine the direction of the iterator.
+ * \brief Node of an AVL tree.
  */
-template< typename Node, typename Node_type, typename Node_op >
-class __Avl_tree_iter : public __Avl_tree_iter_b<Node, Node_op>
+class Avl_tree_node : public Bits::Bst_node
 {
 private:
-  /// Super-class type
-  typedef __Avl_tree_iter_b<Node, Node_op> Base;
-
-  using Base::_n;
-  using Base::_r;
-  using Base::inc;
-
-public:
-  /// Create an invalid iterator (end marker)
-  __Avl_tree_iter() {}
-
-  /**
-   * \brief Create an iterator for the given tree.
-   * \param t the root node of the tree to iterate.
-   * \param cmp the conmparison functor for tree elements.
-   */
-  __Avl_tree_iter(Node const *t) : Base(t) {}
-  __Avl_tree_iter(Node const *t, Node const *r) : Base(t, r) {}
-
-//  template<typename Key2>
-  __Avl_tree_iter(Base const &o) : Base(o) {}
+  template< typename Node, typename Get_key, typename Compare >
+  friend class Avl_tree;
 
-  /**
-   * \brief Dereference the iterator and get the item out of the tree.
-   * \return A reference to the data stored in the AVL tree.
-   */
-  Node_type &operator * () const { return *const_cast<Node *>(_n); }
-  /**
-   * \brief Member access to the item the iterator points to.
-   * \return A pointer to the item in the node.
-   */
-  Node_type *operator -> () const { return const_cast<Node *>(_n); }
-  /**
-   * \brief Set the iterator to the next element (pre increment).
-   */
-  __Avl_tree_iter &operator ++ () { inc(); return *this; }
-  /**
-   * \brief Set the iterator to the next element (post increment).
-   */
-  __Avl_tree_iter &operator ++ (int)
-  { __Avl_tree_iter tmp = *this; inc(); return tmp; }
+  /// Shortcut for Balance values (we use Direction for that).
+  typedef Bits::Direction Bal;
+  /// Alia for Direction.
+  typedef Bits::Direction Dir;
 
-};
+  /// We are a finaly BST node, hide interior.
+  /*@{*/
+  using Bits::Bst_node::next;
+  using Bits::Bst_node::next_p;
+  using Bits::Bst_node::rotate;
+  /*@}*/
 
-class Avl_tree_node
-{
-private:
-  template< typename Node, typename Get_key, typename Compare, bool Const_nodes >
-  friend class Avl_tree;
-  struct Md
-  {
-    Avl_tree_node *left;
-    Avl_tree_node *right;
-    unsigned short flags;
-    short balance;
-    Md() : left(0), right(0), flags(0), balance(0) {}
-  } _md;
+  /// The balance value (#Direction::N is balanced).
+  Bal _balance;
 
 protected:
-  Avl_tree_node() : _md() {}
-
-  void operator = (Avl_tree_node const &)
-  {}
-
+  /// Create an uninitialized node, this is what you shoulkd do.
+  Avl_tree_node() {}
 
 private:
+  /// Hide copy
   Avl_tree_node(Avl_tree_node const &o);
 
-  /// Adjust balance value
-  inline void adj_balance(Avl_tree_node *b, Avl_tree_node *c, int v = -1);
-  /// Replace the child \a c with \a repl.
-  inline void replace_child(Avl_tree_node *c, Avl_tree_node *repl);
+  /// private assignment for initialization and relinkage.
+  void operator = (Avl_tree_node const &o)
+  {
+    Bits::Bst_node::operator = (o);
+    _balance = o._balance;
+  }
+
+  /// Create an initialized node (for internal stuff).
+  explicit Avl_tree_node(bool) : Bits::Bst_node(true), _balance(Dir::N) {}
 
-  /// Right rotation of this node.
-  void r_rotate(Avl_tree_node *r)
-  { _md.left = r->_md.right; r->_md.right = this; }
+  /// Double rotation of \a t.
+  static Bits::Bst_node *rotate2(Bst_node **t, Bal idir, Bal pre);
 
-  /// Left rotation of this node.
-  void l_rotate(Avl_tree_node *r)
-  { _md.right = r->_md.left; r->_md.left = this; }
+  /// Is this subtree balanced?
+  bool balanced() const { return _balance == Bal::N; }
 
-  static void swap(Avl_tree_node *a, Avl_tree_node *b)
-  { Md tmp = a->_md; a->_md = b->_md; b->_md = tmp; }
+  /// What is the balance of this subtree?
+  Bal balance() const { return _balance; }
 
+  /// Set the balance of this subtree to \a b.
+  void balance(Bal b) { _balance = b; }
 };
 
+
+/**
+ * \brief A generic AVL tree.
+ * \param Node the data type of the nodes (must inherit from Avl_tree_noed).
+ * \param Get_key the meta fcuntion to get the key value from a node.
+ *                The implementation uses Get_key::key_of(ptr_to_node).
+ * \param Compare binary relation to establish a total order for the
+ *                nodes of the tree. Compare()(l, r) must return true if
+ *                the key \a l is smaller than the key \a r.
+ */
 template< typename Node, typename Get_key,
-          typename Compare = Lt_functor<typename Get_key::Key_type>,
-          bool Const_nodes = true >
-class Avl_tree
+          typename Compare = Lt_functor<typename Get_key::Key_type> >
+class Avl_tree : public Bits::Bst<Node, Get_key, Compare>
 {
-public:
-  enum
-  {
-    E_noent =  2,
-    E_exist = 17,
-    E_nomem = 12,
-    E_inval = 22
-  };
-
 private:
-  /// Current height of the tree.
-  unsigned long _height;
-  /// Head node of the tree, the root is \a _head.right.
-  Avl_tree_node _head;
+  typedef Bits::Bst<Node, Get_key, Compare> Bst;
 
-  /// Ops for forward iterators
-  struct Fwd
-  {
-    static Node *child1(Node const *n) { return N(n->_md.left); }
-    static Node *child2(Node const *n) { return N(n->_md.right); }
-    static bool cmp(Node const *l, Node const *r)
-    { return Compare()(Get_key::key_of(l), Get_key::key_of(r)); }
-  };
-
-  /// Ops for Reverse iterators
-  struct Rev
-  {
-    static Node *child1(Node const *n) { return N(n->_md.right); }
-    static Node *child2(Node const *n) { return N(n->_md.left); }
-    static bool cmp(Node const *l, Node const *r)
-    { return Compare()(Get_key::key_of(r), Get_key::key_of(l)); }
-  };
+  /// Hide this from possible descendants.
+  using Bst::_head;
+
+  /// Provide access to keys of nodes.
+  using Bst::k;
+
+  /// Alias type for balance values.
+  typedef typename Avl_tree_node::Bal Bal;
+  /// Alias type for Direction values.
+  typedef typename Avl_tree_node::Bal Dir;
 
+  /// Prohibit simple copy.
   Avl_tree(Avl_tree const &o);
 
+  /// Prohibit simple copy.
+  void operator = (Avl_tree const &o);
+
 public:
-  typedef typename Get_key::Key_type Key_type;
-  typedef typename Type_traits<Key_type>::Param_type Key_param_type;
+  //@{
+  typedef typename Bst::Key_type Key_type;
+  typedef typename Bst::Key_param_type Key_param_type;
+  //@}
 
-  typedef Rev Rev_iter_ops;
-  typedef Fwd Fwd_iter_ops;
+  /// Grab iterator types from Bst
+  //@{
   /// Forward iterator for the set.
-  typedef __Avl_tree_iter<Node, Node, Fwd> Iterator;
-  typedef Iterator iterator;
+  typedef typename Bst::Iterator Iterator;
   /// Constant forward iterator for the set.
-  typedef __Avl_tree_iter<Node, Node const, Fwd> Const_iterator;
-  typedef Const_iterator const_iterator;
+  typedef typename Bst::Const_iterator Const_iterator;
   /// Backward iterator for the set.
-  typedef __Avl_tree_iter<Node, Node, Rev> Rev_iterator;
-  typedef Rev_iterator reverse_iterator;
+  typedef typename Bst::Rev_iterator Rev_iterator;
   /// Constant backward iterator for the set.
-  typedef __Avl_tree_iter<Node, Node const, Rev> Const_rev_iterator;
-  typedef Const_rev_iterator const_reverse_iterator;
+  typedef typename Bst::Const_rev_iterator Const_rev_iterator;
+  //@}
 
-  Avl_tree() : _height(0) {}
-  cxx::Pair<Iterator, int> insert(Node *new_node);
+  /**
+   * \brief Insert a new node into this AVL tree.
+   * \param new_node a pointer to the new node. This node must not
+   *                 already b in an AVL tree.
+   * \return A pair, with second set to 'true' and first pointing to
+   *         \a new_node, on success.  If there is already a node with the
+   *         same key that first point to this node and second is 'false'.
+   */
+  Pair<Node *, bool> insert(Node *new_node);
 
   /**
-   * \brief Remove an item from the set.
-   * \param key The item to remove.
-   * \return 0 on success, -3 if the item does not exist, and
-   *         -4 on internal error. 
+   * \brief Remove the node with \a key from the tree.
+   * \param key The node to remove.
+   * \return The pointer to the removed node on success,
+   *         or NULL -3 if no node with the \a key exists.
    */
   Node *remove(Key_param_type key);
-  Node *erase(Key_param_type key) { return remove(key); }
-
   /**
-   * \brief Lookup a node equal to \a key.
-   * \param key The value to search for.
-   * \return A smart pointer to the element found, if no element found the
-   *         pointer is NULL.
+   * \brief An alias for remove().
    */
-  Node *find_node(Key_param_type key) const;
+  Node *erase(Key_param_type key) { return remove(key); }
 
+  /// Create an empty AVL tree.
+  Avl_tree() : Bst() {}
   /// Destroy, and free the set.
   ~Avl_tree()
   {
-    Avl_tree_node const *n;
-    while ((n = _head._md.right))
-      remove(Get_key::key_of(N(n)));
+    Bits::Bst_node const *n;
+    while ((n = _head))
+      remove(k(n));
   }
 
-  /**
-   * \brief Get the constant forward iterator for the first element in the set.
-   * \return Constant forward iterator for the first element in the set.
-   */
-  Const_iterator begin() const { return Const_iterator(N(_head._md.right)); }
-  /**
-   * \brief Get the end marker for the constant forward iterator.
-   * \return The end marker for the constant forward iterator.
-   */
-  Const_iterator end() const   { return Const_iterator(); }
-
-  /**
-   * \brief Get the mutable forward iterator for the first element of the set.
-   * \return The mutable forward iterator for the first element of the set.
-   */
-  Iterator begin() { return Iterator(N(_head._md.right)); }
-  /**
-   * \brief Get the end marker for the mutable forward iterator.
-   * \return The end marker for mutable forward iterator.
-   */
-  Iterator end()   { return Iterator(); }
-
-  /**
-   * \brief Get the constant backward iterator for the last element in the set.
-   * \return The constant backward iterator for the last element in the set.
-   */
-  Const_rev_iterator rbegin() const { return Const_rev_iterator(N(_head._md.right)); }
-  /**
-   * \brief Get the end marker for the constant backward iterator.
-   * \return The end marker for the constant backward iterator.
-   */
-  Const_rev_iterator rend() const   { return Const_rev_iterator(); }
-
-  /**
-   * \brief Get the mutable backward iterator for the last element of the set.
-   * \return The mutable backward iterator for the last element of the set.
-   */
-  Rev_iterator rbegin() { return Rev_iterator(N(_head._md.right)); }
-  /**
-   * \brief Get the end marker for the mutable backward iterator.
-   * \return The end marker for mutable backward iterator.
-   */
-  Rev_iterator rend()   { return Rev_iterator(); }
-
-  Const_iterator find(Key_param_type key) const;
-
-private:
-  static Node *N(Avl_tree_node *n) { return static_cast<Node*>(n); }
-  static Node const *N(Avl_tree_node const *n) { return static_cast<Node const *>(n); }
-
+#ifdef __DEBUG_L4_AVL
+  bool rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx);
+  bool rec_dump(bool print)
+  {
+    int dp=0;
+    return rec_dump(static_cast<Avl_tree_node *>(_head), 0, &dp, print, '+');
+  }
+#endif
 };
 
 
 //----------------------------------------------------------------------------
-/* IMPLEMENTATION: __Avl_tree_iter_b */
+/* IMPLEMENTATION: Bits::__Bst_iter_b */
+
 
-template< typename Node, typename Node_op>
 inline
-void __Avl_tree_iter_b<Node, Node_op>::_downmost()
+Bits::Bst_node *
+Avl_tree_node::rotate2(Bst_node **t, Bal idir, Bal pre)
 {
-  while (_n)
-    {
-      if (Node_op::child1(_n))
-       _n = Node_op::child1(_n);
-      else
-       return;
-    }
-}
+  typedef Bits::Bst_node N;
+  typedef Avl_tree_node A;
+  N *tmp[2] = { *t, N::next(*t, idir) };
+  *t = N::next(tmp[1], !idir);
+  A *n = static_cast<A*>(*t);
 
-template< typename Node, typename Node_op>
-void __Avl_tree_iter_b<Node, Node_op>::inc()
-{
-  if (!_n)
-    return;
+  N::next(tmp[0], idir, N::next(n, !idir));
+  N::next(tmp[1], !idir, N::next(n, idir));
+  N::next(n, !idir, tmp[0]);
+  N::next(n, idir, tmp[1]);
 
-  if (_n == _r)
-    {
-      _r = _n = Node_op::child2(_r);
-      _downmost();
-      return;
-    }
+  n->balance(Bal::N);
 
-  if (Node_op::child2(_n))
+  if (pre == Bal::N)
     {
-      _n = Node_op::child2(_n);
-      _downmost();
-      return;
+      static_cast<A*>(tmp[0])->balance(Bal::N);
+      static_cast<A*>(tmp[1])->balance(Bal::N);
+      return 0;
     }
 
-  Node const *q = _r;
-  Node const *p = _r;
-  while (1)
-    {
-      if (Node_op::cmp(_n, q))
-       {
-         p = q;
-         q = Node_op::child1(q);
-       }
-      else if (_n == q || Node_op::child2(q) == _n)
-       {
-         _n = p;
-         return;
-       }
-      else
-       q = Node_op::child2(q);
-    }
-}
-
-
-
-
+  static_cast<A*>(tmp[pre != idir])->balance(!pre);
+  static_cast<A*>(tmp[pre == idir])->balance(Bal::N);
 
-//----------------------------------------------------------------------------
-/* Implementation of Avl_tree_node */
-inline
-void Avl_tree_node::adj_balance(Avl_tree_node *b, Avl_tree_node *c, int v)
-{
-  if (_md.balance == 0)
-    {
-      b->_md.balance = 0;
-      c->_md.balance = 0;
-    }
-  else if (_md.balance == v)
-    {
-      b->_md.balance = 0;
-      c->_md.balance = -v;
-    }
-  else
-    {
-      b->_md.balance = v;
-      c->_md.balance = 0;
-    }
-  _md.balance = 0;
-}
-
-/* Replace left or right child dependent on comparison. */
-inline
-void Avl_tree_node::replace_child(Avl_tree_node *c, Avl_tree_node *repl)
-{
-  if (_md.right == c)
-    _md.right = repl;
-  else
-    _md.left = repl;
+  return N::next(tmp[pre == idir], !pre);
 }
 
-
 //----------------------------------------------------------------------------
 /* Implementation of AVL Tree */
 
 /* Insert new _Node. */
-template< typename Node, typename Get_key, class Compare, bool Const_nodes>
-cxx::Pair<typename Avl_tree<Node, Get_key, Compare, Const_nodes>::Iterator, int>
-Avl_tree<Node, Get_key, Compare, Const_nodes>::insert(Node *new_node)
+template< typename Node, typename Get_key, class Compare>
+Pair<Node *, bool>
+Avl_tree<Node, Get_key, Compare>::insert(Node *new_node)
 {
-  if (!_head._md.right)
+  typedef Avl_tree_node A;
+  typedef Bits::Bst_node N;
+  N **t = &_head; /* search variable */
+  N **s = &_head; /* node where rebalancing may occur */
+  Key_param_type new_key = Get_key::key_of(new_node);
+
+  // search insertion point
+  for (N *p; (p = *t);)
     {
-      /* empty tree */
-      _head._md.right = new_node;
-      _height = 1;
-    }
-  else
-    {
-      /* non-empty tree */
-      Avl_tree_node *p = _head._md.right; /* search variable */
-      Avl_tree_node *q = 0;           /* new node */
-      Avl_tree_node *r;               /* search variable (balancing) */
-      Avl_tree_node *s = _head._md.right; /* node where rebalancing may occur */
-      Avl_tree_node *t = &_head;      /* parent of s */
-      Compare cmp;
-      int a;                   /* which subtree of s has grown -1 left ... */
-      while (p)
-       {
-         if (cmp(Get_key::key_of(new_node), Get_key::key_of(N(p))))
-           {
-             /* move left */
-             q = p->_md.left;
-             if (!q)
-               {
-                 /* found insert position */
-                 q = new_node;
-                 p->_md.left = new_node;
-                 break;
-               }
-           }
-         else if (cmp(Get_key::key_of(N(p)), Get_key::key_of(new_node)))
-           {
-             /* move right */
-             q = p->_md.right;
-             if (!q)
-               {
-                 /* found insert position */
-                 q = new_node;
-                 p->_md.right = new_node;
-                 break;
-               }
-           }
-         else
-           /* item already exists */
-           return cxx::pair(end(), -E_exist);
-
-         /* insert position not yet found, move on */
-         if (q->_md.balance)
-           {
-             t = p;
-             s = q;
-           }
-
-         p = q;
-       }
+      Dir b = dir(new_key, p);
+      if (b == Dir::N)
+       return pair(static_cast<Node*>(p), false);
 
-      /* adj balanc factors */
-      if (s != &_head && cmp(Get_key::key_of(new_node), Get_key::key_of(N(s))))
-       {
-         a = -1;
-         r = p = s->_md.left;
-       }
-      else
-       {
-         a = +1;
-         r = p = s->_md.right;
-       }
+      if (!static_cast<A const *>(p)->balanced())
+       s = t;
 
-      /* adj balance factors down to the new node */
-      while (p != q)
-       {
-         if (cmp(Get_key::key_of(new_node), Get_key::key_of(N(p))))
-           {
-             p->_md.balance = -1;
-             p = p->_md.left;
-           }
-         else
-           {
-             p->_md.balance = +1;
-             p = p->_md.right;
-           }
-       }
+      t = N::next_p(p, b);
+    }
 
-      /* balancing */
-      if (!s->_md.balance)
-       {
-         /* tree has grown higher */
-         s->_md.balance = a;
-         ++_height;
-         return cxx::pair(Iterator(N(new_node), N(new_node)), 0);
-       }
+  *static_cast<A*>(new_node) = A(true);
+  *t = new_node;
 
-      if (s->_md.balance == -a)
+  N *n = *s;
+  A *a = static_cast<A*>(n);
+  if (!a->balanced())
+    {
+      A::Bal b(greater(new_key, n));
+      if (a->balance() != b)
        {
-         /* node s got balanced (shorter subtree of s has grown) */
-         s->_md.balance = 0;
-         return cxx::pair(Iterator(N(new_node), N(new_node)), 0);
+         // ok we got in balance the shorter subtree go higher
+         a->balance(Bal::N);
+         // propagate the new balance down to the new node
+         n = N::next(n, b);
        }
-
-      /* tree got out of balance */
-      if (r->_md.balance == a)
+      else if (b == Bal(greater(new_key, N::next(n, b))))
        {
-         /* single rotation */
-         p = r;
-         if (a == -1)
-           s->r_rotate(r);
-         else
-           s->l_rotate(r);
-
-         /* set new balance factors */
-         s->_md.balance = 0;
-         r->_md.balance = 0;
+         // left-left or right-right case -> single rotation
+         A::rotate(s, b);
+         a->balance(Bal::N);
+         static_cast<A*>(*s)->balance(Bal::N);
+         n = N::next(*s, b);
        }
       else
        {
-         /* double rotation */
-         if (a == -1)
-           {
-             p = r->_md.right;
-             r->l_rotate(p);
-             s->r_rotate(p);
-           }
-         else
-           {
-             p = r->_md.left;
-             r->r_rotate(p);
-             s->l_rotate(p);
-           }
-
-         /* set new balance factors */
-         p->adj_balance(r, s, a);
+         // need a double rotation
+         n = N::next(N::next(n, b), !b);
+         n = A::rotate2(s, b, n == new_node ? Bal::N : Bal(greater(new_key, n)));
        }
-
-      /* set new subtree head */
-      if (s == t->_md.left)
-       t->_md.left = p;
-      else
-       t->_md.right = p;
-    }
-
-  return cxx::pair(Iterator(N(new_node), N(new_node)), 0);
-}
-
-/* find an element */
-template< typename Node, typename Get_key, class Compare, bool Const_nodes>
-inline
-Node *Avl_tree<Node, Get_key, Compare, Const_nodes>::find_node(Key_param_type key) const
-{
-  Avl_tree_node *q = _head._md.right;
-  Compare cmp;
-
-  while (q)
-    {
-      if (cmp(key, Get_key::key_of(N(q))))
-       q = q->_md.left;
-      else if (cmp(Get_key::key_of(N(q)), key))
-       q = q->_md.right;
-      else
-       return N(q);
     }
-  return 0;
-}
 
-/* find an element */
-template< typename Node, typename Get_key, class Compare, bool Const_nodes>
-inline
-typename Avl_tree<Node, Get_key, Compare, Const_nodes>::Const_iterator
-Avl_tree<Node, Get_key, Compare, Const_nodes>::find(Key_param_type key) const
-{
-  Avl_tree_node *q = _head._md.right;
-  Avl_tree_node *r = q;
-  Compare cmp;
+  for (A::Bal b; n && n != new_node; static_cast<A*>(n)->balance(b), n = N::next(n, b))
+    b = Bal(greater(new_key, n));
 
-  while (q)
-    {
-      if (cmp(key, Get_key::key_of(N(q))))
-       q = q->_md.left;
-      else if (cmp(Get_key::key_of(N(q)), key))
-       {
-         bool qr = (q == r);
-         q = q->_md.right;
-         if (qr)
-           r = q;
-       }
-      else
-       return Iterator(N(q), N(r));
-    }
-  return Iterator();
+  return pair(new_node, true);
 }
 
 
 /* remove an element */
-template< typename Node, typename Get_key, class Compare, bool Const_nodes>
+template< typename Node, typename Get_key, class Compare>
 inline
-Node *Avl_tree<Node, Get_key, Compare, Const_nodes>::remove(Key_param_type key)
+Node *Avl_tree<Node, Get_key, Compare>::remove(Key_param_type key)
 {
-  Avl_tree_node *q = _head._md.right; /* search variable */
-  Avl_tree_node *p = &_head;      /* parent node of q */
-  Avl_tree_node *r;               /* 'symetric predecessor' of q, subtree to rotate 
-                           * while rebalancing */
-  Avl_tree_node *s = &_head;      /* last ('deepest') node on the search path to q
-                           * with balance 0, at this place the rebalancing
-                           * stops in any case */
-  Avl_tree_node *t = 0;           /* parent node of p */
-
-  Compare cmp;
-  Node *removed = 0;
-
-  /***************************************************************************
-   * search node with item == k, on the way down also search for the last
-   * ('deepest') node with balance zero, this is the last node where
-   * rebalancing might be necessary.
-   ***************************************************************************/
-  while (q)
+  typedef Avl_tree_node A;
+  typedef Bits::Bst_node N;
+  N **q = &_head; /* search variable */
+  N **s = &_head; /* last ('deepest') node on the search path to q
+                   * with balance 0, at this place the rebalancing
+                   * stops in any case */
+  N **t = 0;
+  Dir dir;
+
+  // find target node and rebalancing entry
+  for (N *n; (n = *q); q = N::next_p(n, dir))
     {
-      if (!cmp(key, Get_key::key_of(N(q))) && !cmp(Get_key::key_of(N(q)), key))
-       break; /* found */
-
-      if (!q->_md.balance)
-       s = q;
+      dir = Dir(greater(key, n));
+      if (dir == Dir::L && !greater(k(n), key))
+       /* found node */
+       t = q;
 
-      t = p;
-      p = q;
+      if (!N::next(n, dir))
+       break;
 
-      if (cmp(key, Get_key::key_of(N(p))))
-       q = q->_md.left;
-      else if (cmp(Get_key::key_of(N(p)), key))
-       q = q->_md.right;
-      else
-       return 0;
+      A const *a = static_cast<A const *>(n);
+      if (a->balanced() || (a->balance() == !dir && N::next<A>(n, !dir)->balanced()))
+       s = q;
     }
 
-  if (!q)
+  // noting found
+  if (!t)
     return 0;
 
-  /***************************************************************************
-   * remove node
-   ***************************************************************************/
-  if (q->_md.left && q->_md.right)
-    {
-      /* replace q with its 'symetric predecessor' (the node with the largest
-       * item in the left subtree of q, its the rightmost item in this subtree) */     
-      if (!q->_md.balance)
-       s = q;
-  
-      Avl_tree_node *p2 = p;
-      t = p;
-      p = q;
-      r = q->_md.left;
+  A *i = static_cast<A*>(*t);
 
-      while (r->_md.right)
-       {
-         if (r->_md.balance == 0)
-           s = r;
+  for (N *n; (n = *s); s = N::next_p(n, dir))
+    {
+      dir = Dir(greater(key, n));
 
-         t = p;
-         p = r;
-         r = r->_md.right;
-       }
+      if (!N::next(n, dir))
+       break;
 
-      /* found, replace q */
-      if (Const_nodes)
-       {
-         Avl_tree_node::swap(q,r);
-         p2->replace_child(q, r);
-         if (s == q) s = r;
-         if (p == q) p = r;
-         if (t == q) t = r;
-         p->replace_child(r, q);
-       }
+      A *a = static_cast<A*>(n);
+      // got one out of balance
+      if (a->balanced())
+       a->balance(!dir);
+      else if (a->balance() == dir)
+       a->balance(Bal::N);
       else
        {
-         *N(q) = *N(r);
-         q = r;
+         // we need rotations to get in balance
+         Bal b = N::next<A>(n, !dir)->balance();
+         if (b == dir)
+           A::rotate2(s, !dir, N::next<A>(N::next(n, !dir), dir)->balance());
+         else
+           {
+             A::rotate(s, !dir);
+             if (b != Bal::N)
+               {
+                 a->balance(Bal::N);
+                 static_cast<A*>(*s)->balance(Bal::N);
+               }
+             else
+               {
+                 a->balance(!dir);
+                 static_cast<A*>(*s)->balance(dir);
+               }
+           }
+         if (n == i)
+           t = N::next_p(*s, dir);
        }
-#if 0
-      if (!(t->_md.left == p || t->_md.right == p))
-       enter_kdebug("dumb 1");
-
-      if (!(p->_md.left == q || p->_md.right == q))
-       enter_kdebug("dumb 2");
-#endif
     }
 
-  if (q == _head._md.right)
-    {
-      /* remove tree head */
-      if (!q->_md.left && !q->_md.right)
-       {
-         /* got empty tree */
-         _head._md.right = 0;
-         _height = 0;
-       }
-      else
-       {
-         if (q->_md.right)
-           _head._md.right = q->_md.right;
-         else
-           _head._md.right = q->_md.left;
+  A *n = static_cast<A*>(*q);
+  *t = n;
+  *q = N::next(n, !dir);
+  *n = *i;
 
-         --_height;
-       }
-      removed = N(q);
-    }
-  else
-    {
-      /* q is not the tree head */
-      int a;  /* changes of the balance factor, -1 right subtree got
-               * shorter, +1 left subtree got shorter */
+  return static_cast<Node*>(i);
+}
 
-      if (q == p->_md.right)
-       {
-         if (q->_md.left)
-           p->_md.right = q->_md.left;
-         else if (q->_md.right)
-           p->_md.right = q->_md.right;
-         else
-           p->_md.right = 0;
+#ifdef __DEBUG_L4_AVL
+template< typename Node, typename Get_key, class Compare>
+bool Avl_tree<Node, Get_key, Compare>::rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx)
+{
+  typedef Avl_tree_node A;
 
-         /* right subtree of p got shorter */
-         a = -1;
-       }
-      else
-       {
-         if (q->_md.left)
-           p->_md.left = q->_md.left;
-         else if (q->_md.right)
-           p->_md.left = q->_md.right;
-         else
-           p->_md.left = 0;
+  if (!n)
+    return true;
 
-         /* left subtree of p got shorter */
-         a = +1;
-       }
-      removed = N(q);
+  int dpx[2] = {depth,depth};
+  bool res = true;
 
-      /***********************************************************************
-       * Rebalancing 
-       * q is the removed node
-       * p points to the node which must be rebalanced,
-       * t points to the parent node of p
-       * s points to the last node with balance 0 on the way down to p
-       ***********************************************************************/
+  res = rec_dump(n->next<A>(Dir::R), depth + 1, dpx + 1, print, '/');
 
-      Avl_tree_node *o;          /* subtree while rebalancing */
-      bool done = false;  /* done with rebalancing */
+  if (print)
+    {
+      fprintf(stderr, "%2d: [%8p] b=%1d: ", depth, n, (int)n->balance().d);
 
-      do 
-       {
-         if (a == +1)
-           {
-             /***************************************************************
-               * left subtree of p got shorter
-               ***************************************************************/
-             if (p->_md.balance == -1)
-               /* p got balanced => the whole tree with head p got shorter,
-                * must rebalance parent node of p (a.1.) */
-               p->_md.balance = 0;
-             else if (p->_md.balance == 0)
-               {
-                 /* p got out of balance, but kept its overall height
-                  * => done (a.2.) */
-                 p->_md.balance = +1;
-                 done = true;
-               }
-             else
-               {
-                 /* left subtree of p was already shorter than right, 
-                  * need to rotate */
-                 r = p->_md.right;
-                 
-                 if (!r->_md.balance)
-                   {
-                     /* single rotation left and done (a.3.1) */
-                     p->l_rotate(r);
-                     p->_md.balance = +1;
-                     r->_md.balance = -1;
-
-                     t->replace_child(p, r);
-
-                     done = 1;
-                   }
-                 else if (r->_md.balance == +1)
-                   {
-                     /* single rotation left and rebalance parent node 
-                      * (a.3.2) */
-                     p->l_rotate(r);
-                     p->_md.balance = 0;
-                     r->_md.balance = 0;
-
-                     t->replace_child(p, r);
-
-                     p = r;
-                   }
-                 else
-                   {
-                     /* double rotation right - left and rebalance parent 
-                      * node (a.3.3) */
-                     o = r->_md.left;
-                     r->r_rotate(o);
-                     p->l_rotate(o);
-                     t->replace_child(p, o);
-                     o->adj_balance(p, r);
-                     p = o;
-                   }
-               }
-                     
-           }
-         else /* a == -1 */
-           {
-             /***************************************************************
-               * right subtree of p got shorter
-               ***************************************************************/
-             if (p->_md.balance == +1)
-               /* p got balanced,  => the whole tree with head p got 
-                * shorter, must rebalance parent node of p (b.1.) */
-               p->_md.balance = 0;
-             else if (p->_md.balance == 0)
-               {
-                 /* p got out of balance, but kept its overall height 
-                  * => done (b.2.) */
-                 p->_md.balance = -1;
-                 done = true;
-               }
-             else
-               {
-                 /* the right subtree of p already was shorter than the left, 
-                  * need to rotate to rebuild the AVL tree */
-                 r = p->_md.left;
-
-                 if (r->_md.balance == 0)
-                   {
-                     /* single rotation right and done (b.3.1) */
-                     p->r_rotate(r);
-                     r->_md.balance = +1;
-                     p->_md.balance = -1;
-
-                     t->replace_child(p, r);
-
-                     done = true;
-                   }
-                 else if (r->_md.balance == -1)
-                   {
-                     /* single rotation right and rebalance parent
-                      * node (b.3.2) */
-                     p->r_rotate(r);
-                     r->_md.balance = 0;
-                     p->_md.balance = 0;
-
-                     t->replace_child(p, r);
-                     p = r;
-                   }
-                 else
-                   {
-                     /* double rotation left - right and rebalance parent
-                      * node (b.3.3) */
-                     o = r->_md.right;
-                     r->l_rotate(o);
-                     p->r_rotate(o);
-                     t->replace_child(p, o);
-                     o->adj_balance(r, p);
-                     p = o;
-                   }
-               }
-           }
+      for (int i = 0; i < depth; ++i)
+       std::cerr << "    ";
 
-         if (!done)
-           {
-             /* need to rebalance parent node, go one level up in the tree.
-              * Actually, we go down the tree until we find p and store its 
-              * parent and the parent of the parent. We start at the last 
-              * node with balance 0, because the rebalancing definitely 
-              * stops there. 
-              * Current situation: 
-              * t points to the node which must be rebalanced, p to the 
-              * subtree of t which got shorter */
-             q = p;
-             r = t;
-             if (t == s)
-               {
-                 if (s == &_head)
-                   {
-                     /* whole tree got shorter */
-                     --_height;
-                     done = true;
-                   }
-                 else
-                   {
-                     /* reached the last node which needs to be rebalanced */
-                     p = s;
-                     if (p->_md.left == q)
-                       /* left subtree got shorter */
-                       a = +1;
-                     else if (p->_md.right == q)
-                       /* right subtree got shorter */
-                       a = -1;
-                     else
-                       return (Node*)-E_inval;
-                   }
-               }
-             else
-               {
-                 /* search node q */
-
-                 t = p = s;
-
-                 if (s == &_head)
-                   p = s->_md.right;
-
-                 while (p && (p != r))
-                   {
-                     t = p;
-                     if (cmp(Get_key::key_of(N(q)), Get_key::key_of(N(p))))
-                       p = p->_md.left;
-                     else
-                       p = p->_md.right;
-                   }
-#if 0
-                 if (!p) enter_kdebug("dd");
-#endif
-                 if (p->_md.left == q)
-                   /* left subtree got shorter */
-                   a = +1;
-                 else if (p->_md.right == q)
-                   /* right subtree got shorter */
-                   a = -1;
-                 else
-                   return (Node*)-E_inval;
-               }
-           }
-       }
-      while (!done);
+      std::cerr << pfx << (static_cast<Node*>(n)->item) << std::endl;
     }
 
-  /* done */
-  return removed;
+  res = res & rec_dump(n->next<A>(Dir::L), depth + 1, dpx, print, '\\');
+
+  int b = dpx[1] - dpx[0];
+
+  if (b < 0)
+    *dp = dpx[0];
+  else
+    *dp = dpx[1];
+
+  Bal x = n->balance();
+  if ((b < -1 || b > 1) ||
+      (b == 0 && x != Bal::N) ||
+      (b == -1 && x != Bal::L) ||
+      (b == 1 && x != Bal::R))
+    {
+      if (print)
+       fprintf(stderr, "%2d: [%8p] b=%1d: balance error %d\n", depth, n, (int)n->balance().d, b);
+      return false;
+    }
+  return res;
 }
+#endif
 
 }