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)
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.
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.
31 #include "bits/bst_iter.h"
36 * \brief Node of an AVL tree.
38 class Avl_tree_node : public Bits::Bst_node
41 template< typename Node, typename Get_key, typename Compare >
42 friend class Avl_tree;
44 /// Shortcut for Balance values (we use Direction for that).
45 typedef Bits::Direction Bal;
46 /// Alia for Direction.
47 typedef Bits::Direction Dir;
49 /// We are a finaly BST node, hide interior.
51 using Bits::Bst_node::next;
52 using Bits::Bst_node::next_p;
53 using Bits::Bst_node::rotate;
56 /// The balance value (#Direction::N is balanced).
60 /// Create an uninitialized node, this is what you shoulkd do.
65 Avl_tree_node(Avl_tree_node const &o);
67 /// private assignment for initialization and relinkage.
68 void operator = (Avl_tree_node const &o)
70 Bits::Bst_node::operator = (o);
71 _balance = o._balance;
74 /// Create an initialized node (for internal stuff).
75 explicit Avl_tree_node(bool) : Bits::Bst_node(true), _balance(Dir::N) {}
77 /// Double rotation of \a t.
78 static Bits::Bst_node *rotate2(Bst_node **t, Bal idir, Bal pre);
80 /// Is this subtree balanced?
81 bool balanced() const { return _balance == Bal::N; }
83 /// What is the balance of this subtree?
84 Bal balance() const { return _balance; }
86 /// Set the balance of this subtree to \a b.
87 void balance(Bal b) { _balance = b; }
92 * \brief A generic AVL tree.
93 * \param Node the data type of the nodes (must inherit from Avl_tree_noed).
94 * \param Get_key the meta fcuntion to get the key value from a node.
95 * The implementation uses Get_key::key_of(ptr_to_node).
96 * \param Compare binary relation to establish a total order for the
97 * nodes of the tree. Compare()(l, r) must return true if
98 * the key \a l is smaller than the key \a r.
100 template< typename Node, typename Get_key,
101 typename Compare = Lt_functor<typename Get_key::Key_type> >
102 class Avl_tree : public Bits::Bst<Node, Get_key, Compare>
105 typedef Bits::Bst<Node, Get_key, Compare> Bst;
107 /// Hide this from possible descendants.
110 /// Provide access to keys of nodes.
113 /// Alias type for balance values.
114 typedef typename Avl_tree_node::Bal Bal;
115 /// Alias type for Direction values.
116 typedef typename Avl_tree_node::Bal Dir;
118 /// Prohibit simple copy.
119 Avl_tree(Avl_tree const &o);
121 /// Prohibit simple copy.
122 void operator = (Avl_tree const &o);
126 typedef typename Bst::Key_type Key_type;
127 typedef typename Bst::Key_param_type Key_param_type;
130 /// Grab iterator types from Bst
132 /// Forward iterator for the set.
133 typedef typename Bst::Iterator Iterator;
134 /// Constant forward iterator for the set.
135 typedef typename Bst::Const_iterator Const_iterator;
136 /// Backward iterator for the set.
137 typedef typename Bst::Rev_iterator Rev_iterator;
138 /// Constant backward iterator for the set.
139 typedef typename Bst::Const_rev_iterator Const_rev_iterator;
143 * \brief Insert a new node into this AVL tree.
144 * \param new_node a pointer to the new node. This node must not
145 * already b in an AVL tree.
146 * \return A pair, with second set to 'true' and first pointing to
147 * \a new_node, on success. If there is already a node with the
148 * same key that first point to this node and second is 'false'.
150 Pair<Node *, bool> insert(Node *new_node);
153 * \brief Remove the node with \a key from the tree.
154 * \param key The node to remove.
155 * \return The pointer to the removed node on success,
156 * or NULL -3 if no node with the \a key exists.
158 Node *remove(Key_param_type key);
160 * \brief An alias for remove().
162 Node *erase(Key_param_type key) { return remove(key); }
164 /// Create an empty AVL tree.
165 Avl_tree() : Bst() {}
166 /// Destroy, and free the set.
169 Bits::Bst_node const *n;
174 #ifdef __DEBUG_L4_AVL
175 bool rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx);
176 bool rec_dump(bool print)
179 return rec_dump(static_cast<Avl_tree_node *>(_head), 0, &dp, print, '+');
185 //----------------------------------------------------------------------------
186 /* IMPLEMENTATION: Bits::__Bst_iter_b */
191 Avl_tree_node::rotate2(Bst_node **t, Bal idir, Bal pre)
193 typedef Bits::Bst_node N;
194 typedef Avl_tree_node A;
195 N *tmp[2] = { *t, N::next(*t, idir) };
196 *t = N::next(tmp[1], !idir);
197 A *n = static_cast<A*>(*t);
199 N::next(tmp[0], idir, N::next(n, !idir));
200 N::next(tmp[1], !idir, N::next(n, idir));
201 N::next(n, !idir, tmp[0]);
202 N::next(n, idir, tmp[1]);
208 static_cast<A*>(tmp[0])->balance(Bal::N);
209 static_cast<A*>(tmp[1])->balance(Bal::N);
213 static_cast<A*>(tmp[pre != idir])->balance(!pre);
214 static_cast<A*>(tmp[pre == idir])->balance(Bal::N);
216 return N::next(tmp[pre == idir], !pre);
219 //----------------------------------------------------------------------------
220 /* Implementation of AVL Tree */
222 /* Insert new _Node. */
223 template< typename Node, typename Get_key, class Compare>
225 Avl_tree<Node, Get_key, Compare>::insert(Node *new_node)
227 typedef Avl_tree_node A;
228 typedef Bits::Bst_node N;
229 N **t = &_head; /* search variable */
230 N **s = &_head; /* node where rebalancing may occur */
231 Key_param_type new_key = Get_key::key_of(new_node);
233 // search insertion point
234 for (N *p; (p = *t);)
236 Dir b = dir(new_key, p);
238 return pair(static_cast<Node*>(p), false);
240 if (!static_cast<A const *>(p)->balanced())
246 *static_cast<A*>(new_node) = A(true);
250 A *a = static_cast<A*>(n);
253 A::Bal b(greater(new_key, n));
254 if (a->balance() != b)
256 // ok we got in balance the shorter subtree go higher
258 // propagate the new balance down to the new node
261 else if (b == Bal(greater(new_key, N::next(n, b))))
263 // left-left or right-right case -> single rotation
266 static_cast<A*>(*s)->balance(Bal::N);
271 // need a double rotation
272 n = N::next(N::next(n, b), !b);
273 n = A::rotate2(s, b, n == new_node ? Bal::N : Bal(greater(new_key, n)));
277 for (A::Bal b; n && n != new_node; static_cast<A*>(n)->balance(b), n = N::next(n, b))
278 b = Bal(greater(new_key, n));
280 return pair(new_node, true);
284 /* remove an element */
285 template< typename Node, typename Get_key, class Compare>
287 Node *Avl_tree<Node, Get_key, Compare>::remove(Key_param_type key)
289 typedef Avl_tree_node A;
290 typedef Bits::Bst_node N;
291 N **q = &_head; /* search variable */
292 N **s = &_head; /* last ('deepest') node on the search path to q
293 * with balance 0, at this place the rebalancing
294 * stops in any case */
298 // find target node and rebalancing entry
299 for (N *n; (n = *q); q = N::next_p(n, dir))
301 dir = Dir(greater(key, n));
302 if (dir == Dir::L && !greater(k(n), key))
306 if (!N::next(n, dir))
309 A const *a = static_cast<A const *>(n);
310 if (a->balanced() || (a->balance() == !dir && N::next<A>(n, !dir)->balanced()))
318 A *i = static_cast<A*>(*t);
320 for (N *n; (n = *s); s = N::next_p(n, dir))
322 dir = Dir(greater(key, n));
324 if (!N::next(n, dir))
327 A *a = static_cast<A*>(n);
328 // got one out of balance
331 else if (a->balance() == dir)
335 // we need rotations to get in balance
336 Bal b = N::next<A>(n, !dir)->balance();
338 A::rotate2(s, !dir, N::next<A>(N::next(n, !dir), dir)->balance());
345 static_cast<A*>(*s)->balance(Bal::N);
350 static_cast<A*>(*s)->balance(dir);
354 t = N::next_p(*s, dir);
358 A *n = static_cast<A*>(*q);
360 *q = N::next(n, !dir);
363 return static_cast<Node*>(i);
366 #ifdef __DEBUG_L4_AVL
367 template< typename Node, typename Get_key, class Compare>
368 bool Avl_tree<Node, Get_key, Compare>::rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx)
370 typedef Avl_tree_node A;
375 int dpx[2] = {depth,depth};
378 res = rec_dump(n->next<A>(Dir::R), depth + 1, dpx + 1, print, '/');
382 fprintf(stderr, "%2d: [%8p] b=%1d: ", depth, n, (int)n->balance().d);
384 for (int i = 0; i < depth; ++i)
387 std::cerr << pfx << (static_cast<Node*>(n)->item) << std::endl;
390 res = res & rec_dump(n->next<A>(Dir::L), depth + 1, dpx, print, '\\');
392 int b = dpx[1] - dpx[0];
399 Bal x = n->balance();
400 if ((b < -1 || b > 1) ||
401 (b == 0 && x != Bal::N) ||
402 (b == -1 && x != Bal::L) ||
403 (b == 1 && x != Bal::R))
406 fprintf(stderr, "%2d: [%8p] b=%1d: balance error %d\n", depth, n, (int)n->balance().d, b);