L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 * License: see LICENSE.spdx (in this directory or the directories above)
12 */
13
14#pragma once
15
16#include "std_ops"
17#include "pair"
18
19#include "bits/bst.h"
20#include "bits/bst_iter.h"
21
22struct Avl_set_tester;
23
24namespace cxx {
25
30{
31 friend struct ::Avl_set_tester;
32
33private:
34 template< typename Node, typename Get_key, typename Compare >
35 friend class Avl_tree;
36
38 typedef Bits::Direction Bal;
40 typedef Bits::Direction Dir;
41
42 // We are a final BST node, hide interior.
50 Bal _balance;
51
52protected:
54 Avl_tree_node() = default;
55
56private:
57 Avl_tree_node(Avl_tree_node const &o) = delete;
58 Avl_tree_node(Avl_tree_node &&o) = delete;
59
61 Avl_tree_node &operator = (Avl_tree_node const &o) = default;
63 Avl_tree_node &operator = (Avl_tree_node &&o) = default;
64
66 explicit Avl_tree_node(bool) : Bits::Bst_node(true), _balance(Dir::N) {}
67
69 static Bits::Bst_node *rotate2(Bst_node **t, Bal idir, Bal pre);
70
72 bool balanced() const { return _balance == Bal::N; }
73
75 Bal balance() const { return _balance; }
76
78 void balance(Bal b) { _balance = b; }
79};
80
81
98template< typename Node, typename Get_key,
99 typename Compare = Lt_functor<typename Get_key::Key_type> >
100class Avl_tree : public Bits::Bst<Node, Get_key, Compare>
101{
102private:
104
106 using Bst::_head;
107
109 using Bst::k;
110
112 typedef typename Avl_tree_node::Bal Bal;
114 typedef typename Avl_tree_node::Bal Dir;
115
116 Avl_tree(Avl_tree const &o) = delete;
117 Avl_tree &operator = (Avl_tree const &o) = delete;
118 Avl_tree(Avl_tree &&o) = delete;
119 Avl_tree &operator = (Avl_tree &&o) = delete;
120
121public:
123 typedef typename Bst::Key_type Key_type;
124 typedef typename Bst::Key_param_type Key_param_type;
126
127 // Grab iterator types from Bst
130 typedef typename Bst::Iterator Iterator;
138
146 Pair<Node *, bool> insert(Node *new_node);
147
154 Node *remove(Key_param_type key);
158 Node *erase(Key_param_type key) { return remove(key); }
159
161 Avl_tree() = default;
162
164 ~Avl_tree() noexcept
165 {
166 this->remove_all([](Node *){});
167 }
168
169#ifdef __DEBUG_L4_AVL
170 bool rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx);
171 bool rec_dump(bool print)
172 {
173 int dp=0;
174 return rec_dump(static_cast<Avl_tree_node *>(_head), 0, &dp, print, '+');
175 }
176#endif
177};
178
179
180//----------------------------------------------------------------------------
181/* IMPLEMENTATION: Bits::__Bst_iter_b */
182
183
184inline
185Bits::Bst_node *
186Avl_tree_node::rotate2(Bst_node **t, Bal idir, Bal pre)
187{
188 typedef Bits::Bst_node N;
189 typedef Avl_tree_node A;
190 N *tmp[2] = { *t, N::next(*t, idir) };
191 *t = N::next(tmp[1], !idir);
192 A *n = static_cast<A*>(*t);
193
194 N::next(tmp[0], idir, N::next(n, !idir));
195 N::next(tmp[1], !idir, N::next(n, idir));
196 N::next(n, !idir, tmp[0]);
197 N::next(n, idir, tmp[1]);
198
199 n->balance(Bal::N);
200
201 if (pre == Bal::N)
202 {
203 static_cast<A*>(tmp[0])->balance(Bal::N);
204 static_cast<A*>(tmp[1])->balance(Bal::N);
205 return 0;
206 }
207
208 static_cast<A*>(tmp[pre != idir])->balance(!pre);
209 static_cast<A*>(tmp[pre == idir])->balance(Bal::N);
210
211 return N::next(tmp[pre == idir], !pre);
212}
213
214//----------------------------------------------------------------------------
215/* Implementation of AVL Tree */
216
217/* Insert new _Node. */
218template< typename Node, typename Get_key, class Compare>
219Pair<Node *, bool>
221{
222 typedef Avl_tree_node A;
223 typedef Bits::Bst_node N;
224 N **t = &_head; /* search variable */
225 N **s = &_head; /* node where rebalancing may occur */
226 Key_param_type new_key = Get_key::key_of(new_node);
227
228 // search insertion point
229 for (N *p; (p = *t);)
230 {
231 Dir b = this->dir(new_key, p);
232 if (b == Dir::N)
233 return pair(static_cast<Node*>(p), false);
234
235 if (!static_cast<A const *>(p)->balanced())
236 s = t;
237
238 t = A::next_p(p, b);
239 }
240
241 *static_cast<A*>(new_node) = A(true);
242 *t = new_node;
243
244 N *n = *s;
245 A *a = static_cast<A*>(n);
246 if (!a->balanced())
247 {
248 A::Bal b(this->greater(new_key, n));
249 if (a->balance() != b)
250 {
251 // ok we got in balance the shorter subtree go higher
252 a->balance(Bal::N);
253 // propagate the new balance down to the new node
254 n = A::next(n, b);
255 }
256 else if (b == Bal(this->greater(new_key, A::next(n, b))))
257 {
258 // left-left or right-right case -> single rotation
259 A::rotate(s, b);
260 a->balance(Bal::N);
261 static_cast<A*>(*s)->balance(Bal::N);
262 n = A::next(*s, b);
263 }
264 else
265 {
266 // need a double rotation
267 n = A::next(A::next(n, b), !b);
268 n = A::rotate2(s, b, n == new_node ? Bal::N : Bal(this->greater(new_key, n)));
269 }
270 }
271
272 for (A::Bal b; n && n != new_node; static_cast<A*>(n)->balance(b), n = A::next(n, b))
273 b = Bal(this->greater(new_key, n));
274
275 return pair(new_node, true);
276}
277
278
279/* remove an element */
280template< typename Node, typename Get_key, class Compare>
281inline
283{
284 typedef Avl_tree_node A;
285 typedef Bits::Bst_node N;
286 N **q = &_head; /* search variable */
287 N **s = &_head; /* last ('deepest') node on the search path to q
288 * with balance 0, at this place the rebalancing
289 * stops in any case */
290 N **t = 0;
291 Dir dir;
292
293 // find target node and rebalancing entry
294 for (N *n; (n = *q); q = A::next_p(n, dir))
295 {
296 dir = Dir(this->greater(key, n));
297 if (dir == Dir::L && !this->greater(k(n), key))
298 /* found node */
299 t = q;
300
301 if (!A::next(n, dir))
302 break;
303
304 A const *a = static_cast<A const *>(n);
305 if (a->balanced() || (a->balance() == !dir && A::next<A>(n, !dir)->balanced()))
306 s = q;
307 }
308
309 // nothing found
310 if (!t)
311 return 0;
312
313 A *i = static_cast<A*>(*t);
314
315 for (N *n; (n = *s); s = A::next_p(n, dir))
316 {
317 dir = Dir(this->greater(key, n));
318
319 if (!A::next(n, dir))
320 break;
321
322 A *a = static_cast<A*>(n);
323 // got one out of balance
324 if (a->balanced())
325 a->balance(!dir);
326 else if (a->balance() == dir)
327 a->balance(Bal::N);
328 else
329 {
330 // we need rotations to get in balance
331 Bal b = A::next<A>(n, !dir)->balance();
332 if (b == dir)
333 A::rotate2(s, !dir, A::next<A>(A::next(n, !dir), dir)->balance());
334 else
335 {
336 A::rotate(s, !dir);
337 if (b != Bal::N)
338 {
339 a->balance(Bal::N);
340 static_cast<A*>(*s)->balance(Bal::N);
341 }
342 else
343 {
344 a->balance(!dir);
345 static_cast<A*>(*s)->balance(dir);
346 }
347 }
348 if (n == i)
349 t = A::next_p(*s, dir);
350 }
351 }
352
353 A *n = static_cast<A*>(*q);
354 *t = n;
355 *q = A::next(n, !dir);
356 *n = *i;
357
358 return static_cast<Node*>(i);
359}
360
361#ifdef __DEBUG_L4_AVL
362template< typename Node, typename Get_key, class Compare>
363bool Avl_tree<Node, Get_key, Compare>::rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx)
364{
365 typedef Avl_tree_node A;
366
367 if (!n)
368 return true;
369
370 int dpx[2] = {depth,depth};
371 bool res = true;
372
373 res = rec_dump(A::next<A>(n, Dir::R), depth + 1, dpx + 1, print, '/');
374
375 if (print)
376 {
377 fprintf(stderr, "%2d: [%8p] b=%1d: ", depth, n, (int)n->balance().d);
378
379 for (int i = 0; i < depth; ++i)
380 std::cerr << " ";
381
382 std::cerr << pfx << (static_cast<Node*>(n)->item) << std::endl;
383 }
384
385 res = res & rec_dump(A::next<A>(n, Dir::L), depth + 1, dpx, print, '\\');
386
387 int b = dpx[1] - dpx[0];
388
389 if (b < 0)
390 *dp = dpx[0];
391 else
392 *dp = dpx[1];
393
394 Bal x = n->balance();
395 if ((b < -1 || b > 1) ||
396 (b == 0 && x != Bal::N) ||
397 (b == -1 && x != Bal::L) ||
398 (b == 1 && x != Bal::R))
399 {
400 if (print)
401 fprintf(stderr, "%2d: [%8p] b=%1d: balance error %d\n", depth, n, (int)n->balance().d, b);
402 return false;
403 }
404 return res;
405}
406#endif
407
408}
409
AVL tree.
AVL tree.
Node of an AVL tree.
Definition avl_tree:30
Avl_tree_node()=default
Create an uninitialized node, this is what you should do.
A generic AVL tree.
Definition avl_tree:101
Pair< Node *, bool > insert(Node *new_node)
Insert a new node into this AVL tree.
Definition avl_tree:220
Node * erase(Key_param_type key)
An alias for remove().
Definition avl_tree:158
Node * remove(Key_param_type key)
Remove the node with key from the tree.
Definition avl_tree:282
~Avl_tree() noexcept
Destroy the tree.
Definition avl_tree:164
Avl_tree()=default
Create an empty AVL tree.
Bst::Const_iterator Const_iterator
Constant forward iterator for the tree.
Definition avl_tree:132
Bst::Rev_iterator Rev_iterator
Backward iterator for the tree.
Definition avl_tree:134
Bst::Iterator Iterator
Definition avl_tree:130
Bst::Const_rev_iterator Const_rev_iterator
Constant backward iterator for the tree.
Definition avl_tree:136
Basic type of a node in a binary search tree (BST).
Definition bst_base.h:71
static Bst_node ** next_p(Bst_node *p, Direction d)
Get pointer to link in direction d.
Definition bst_base.h:95
static void rotate(Bst_node **t, Direction idir)
Rotate subtree t in the opposite direction of idir.
Definition bst_base.h:120
Bst_node()
Create uninitialized node.
Definition bst_base.h:112
static Bst_node * next(Bst_node const *p, Direction d)
Get next node in direction d.
Definition bst_base.h:87
Basic binary search tree (BST).
Definition bst.h:32
__Bst_iter< Node, Node const, Rev > Const_rev_iterator
Constant backward.
Definition bst.h:77
Get_key::Key_type Key_type
The type of key values used to generate the total order of the elements.
Definition bst.h:59
__Bst_iter< Node, Node, Fwd > Iterator
Forward iterator.
Definition bst.h:71
Type_traits< Key_type >::Param_type Key_param_type
The type for key parameters.
Definition bst.h:61
Bst_node * _head
The head pointer of the tree.
Definition bst.h:91
__Bst_iter< Node, Node const, Fwd > Const_iterator
Constant forward iterator.
Definition bst.h:73
void remove_all(FUNC &&callback)
Clear the tree.
Definition bst.h:251
static Key_type k(Bst_node const *n)
Get the key value of n.
Definition bst.h:100
__Bst_iter< Node, Node, Rev > Rev_iterator
Backward iterator.
Definition bst.h:75
Our C++ library.
Definition arith:11
Pair implementation.
The direction to go in a binary search tree.
Definition bst_base.h:29
Pair of two values.
Definition pair:28