L4Re Operating System Framework – Interface and Usage Documentation
Loading...
Searching...
No Matches
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
33namespace cxx {
34
39{
40private:
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.
57 Bal _balance;
58
59protected:
61 Avl_tree_node() = default;
62
63private:
64 Avl_tree_node(Avl_tree_node const &o) = delete;
65 Avl_tree_node(Avl_tree_node &&o) = delete;
66
68 Avl_tree_node &operator = (Avl_tree_node const &o) = default;
70 Avl_tree_node &operator = (Avl_tree_node &&o) = default;
71
73 explicit Avl_tree_node(bool) : Bits::Bst_node(true), _balance(Dir::N) {}
74
76 static Bits::Bst_node *rotate2(Bst_node **t, Bal idir, Bal pre);
77
79 bool balanced() const { return _balance == Bal::N; }
80
82 Bal balance() const { return _balance; }
83
85 void balance(Bal b) { _balance = b; }
86};
87
88
105template< typename Node, typename Get_key,
106 typename Compare = Lt_functor<typename Get_key::Key_type> >
107class Avl_tree : public Bits::Bst<Node, Get_key, Compare>
108{
109private:
111
113 using Bst::_head;
114
116 using Bst::k;
117
119 typedef typename Avl_tree_node::Bal Bal;
121 typedef typename Avl_tree_node::Bal Dir;
122
123 Avl_tree(Avl_tree const &o) = delete;
124 Avl_tree &operator = (Avl_tree const &o) = delete;
125 Avl_tree(Avl_tree &&o) = delete;
126 Avl_tree &operator = (Avl_tree &&o) = delete;
127
128public:
130 typedef typename Bst::Key_type Key_type;
131 typedef typename Bst::Key_param_type Key_param_type;
133
134 // Grab iterator types from Bst
137 typedef typename Bst::Iterator Iterator;
145
153 Pair<Node *, bool> insert(Node *new_node);
154
161 Node *remove(Key_param_type key);
165 Node *erase(Key_param_type key) { return remove(key); }
166
168 Avl_tree() = default;
169
171 ~Avl_tree() noexcept
172 {
173 this->remove_all([](Node *){});
174 }
175
176#ifdef __DEBUG_L4_AVL
177 bool rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx);
178 bool rec_dump(bool print)
179 {
180 int dp=0;
181 return rec_dump(static_cast<Avl_tree_node *>(_head), 0, &dp, print, '+');
182 }
183#endif
184};
185
186
187//----------------------------------------------------------------------------
188/* IMPLEMENTATION: Bits::__Bst_iter_b */
189
190
191inline
192Bits::Bst_node *
193Avl_tree_node::rotate2(Bst_node **t, Bal idir, Bal pre)
194{
195 typedef Bits::Bst_node N;
196 typedef Avl_tree_node A;
197 N *tmp[2] = { *t, N::next(*t, idir) };
198 *t = N::next(tmp[1], !idir);
199 A *n = static_cast<A*>(*t);
200
201 N::next(tmp[0], idir, N::next(n, !idir));
202 N::next(tmp[1], !idir, N::next(n, idir));
203 N::next(n, !idir, tmp[0]);
204 N::next(n, idir, tmp[1]);
205
206 n->balance(Bal::N);
207
208 if (pre == Bal::N)
209 {
210 static_cast<A*>(tmp[0])->balance(Bal::N);
211 static_cast<A*>(tmp[1])->balance(Bal::N);
212 return 0;
213 }
214
215 static_cast<A*>(tmp[pre != idir])->balance(!pre);
216 static_cast<A*>(tmp[pre == idir])->balance(Bal::N);
217
218 return N::next(tmp[pre == idir], !pre);
219}
220
221//----------------------------------------------------------------------------
222/* Implementation of AVL Tree */
223
224/* Insert new _Node. */
225template< typename Node, typename Get_key, class Compare>
226Pair<Node *, bool>
228{
229 typedef Avl_tree_node A;
230 typedef Bits::Bst_node N;
231 N **t = &_head; /* search variable */
232 N **s = &_head; /* node where rebalancing may occur */
233 Key_param_type new_key = Get_key::key_of(new_node);
234
235 // search insertion point
236 for (N *p; (p = *t);)
237 {
238 Dir b = this->dir(new_key, p);
239 if (b == Dir::N)
240 return pair(static_cast<Node*>(p), false);
241
242 if (!static_cast<A const *>(p)->balanced())
243 s = t;
244
245 t = A::next_p(p, b);
246 }
247
248 *static_cast<A*>(new_node) = A(true);
249 *t = new_node;
250
251 N *n = *s;
252 A *a = static_cast<A*>(n);
253 if (!a->balanced())
254 {
255 A::Bal b(this->greater(new_key, n));
256 if (a->balance() != b)
257 {
258 // ok we got in balance the shorter subtree go higher
259 a->balance(Bal::N);
260 // propagate the new balance down to the new node
261 n = A::next(n, b);
262 }
263 else if (b == Bal(this->greater(new_key, A::next(n, b))))
264 {
265 // left-left or right-right case -> single rotation
266 A::rotate(s, b);
267 a->balance(Bal::N);
268 static_cast<A*>(*s)->balance(Bal::N);
269 n = A::next(*s, b);
270 }
271 else
272 {
273 // need a double rotation
274 n = A::next(A::next(n, b), !b);
275 n = A::rotate2(s, b, n == new_node ? Bal::N : Bal(this->greater(new_key, n)));
276 }
277 }
278
279 for (A::Bal b; n && n != new_node; static_cast<A*>(n)->balance(b), n = A::next(n, b))
280 b = Bal(this->greater(new_key, n));
281
282 return pair(new_node, true);
283}
284
285
286/* remove an element */
287template< typename Node, typename Get_key, class Compare>
288inline
290{
291 typedef Avl_tree_node A;
292 typedef Bits::Bst_node N;
293 N **q = &_head; /* search variable */
294 N **s = &_head; /* last ('deepest') node on the search path to q
295 * with balance 0, at this place the rebalancing
296 * stops in any case */
297 N **t = 0;
298 Dir dir;
299
300 // find target node and rebalancing entry
301 for (N *n; (n = *q); q = A::next_p(n, dir))
302 {
303 dir = Dir(this->greater(key, n));
304 if (dir == Dir::L && !this->greater(k(n), key))
305 /* found node */
306 t = q;
307
308 if (!A::next(n, dir))
309 break;
310
311 A const *a = static_cast<A const *>(n);
312 if (a->balanced() || (a->balance() == !dir && A::next<A>(n, !dir)->balanced()))
313 s = q;
314 }
315
316 // nothing found
317 if (!t)
318 return 0;
319
320 A *i = static_cast<A*>(*t);
321
322 for (N *n; (n = *s); s = A::next_p(n, dir))
323 {
324 dir = Dir(this->greater(key, n));
325
326 if (!A::next(n, dir))
327 break;
328
329 A *a = static_cast<A*>(n);
330 // got one out of balance
331 if (a->balanced())
332 a->balance(!dir);
333 else if (a->balance() == dir)
334 a->balance(Bal::N);
335 else
336 {
337 // we need rotations to get in balance
338 Bal b = A::next<A>(n, !dir)->balance();
339 if (b == dir)
340 A::rotate2(s, !dir, A::next<A>(A::next(n, !dir), dir)->balance());
341 else
342 {
343 A::rotate(s, !dir);
344 if (b != Bal::N)
345 {
346 a->balance(Bal::N);
347 static_cast<A*>(*s)->balance(Bal::N);
348 }
349 else
350 {
351 a->balance(!dir);
352 static_cast<A*>(*s)->balance(dir);
353 }
354 }
355 if (n == i)
356 t = A::next_p(*s, dir);
357 }
358 }
359
360 A *n = static_cast<A*>(*q);
361 *t = n;
362 *q = A::next(n, !dir);
363 *n = *i;
364
365 return static_cast<Node*>(i);
366}
367
368#ifdef __DEBUG_L4_AVL
369template< typename Node, typename Get_key, class Compare>
370bool Avl_tree<Node, Get_key, Compare>::rec_dump(Avl_tree_node *n, int depth, int *dp, bool print, char pfx)
371{
372 typedef Avl_tree_node A;
373
374 if (!n)
375 return true;
376
377 int dpx[2] = {depth,depth};
378 bool res = true;
379
380 res = rec_dump(A::next<A>(n, Dir::R), depth + 1, dpx + 1, print, '/');
381
382 if (print)
383 {
384 fprintf(stderr, "%2d: [%8p] b=%1d: ", depth, n, (int)n->balance().d);
385
386 for (int i = 0; i < depth; ++i)
387 std::cerr << " ";
388
389 std::cerr << pfx << (static_cast<Node*>(n)->item) << std::endl;
390 }
391
392 res = res & rec_dump(A::next<A>(n, Dir::L), depth + 1, dpx, print, '\\');
393
394 int b = dpx[1] - dpx[0];
395
396 if (b < 0)
397 *dp = dpx[0];
398 else
399 *dp = dpx[1];
400
401 Bal x = n->balance();
402 if ((b < -1 || b > 1) ||
403 (b == 0 && x != Bal::N) ||
404 (b == -1 && x != Bal::L) ||
405 (b == 1 && x != Bal::R))
406 {
407 if (print)
408 fprintf(stderr, "%2d: [%8p] b=%1d: balance error %d\n", depth, n, (int)n->balance().d, b);
409 return false;
410 }
411 return res;
412}
413#endif
414
415}
416
AVL tree.
AVL tree.
Node of an AVL tree.
Definition avl_tree:39
Avl_tree_node()=default
Create an uninitialized node, this is what you should do.
A generic AVL tree.
Definition avl_tree:108
Pair< Node *, bool > insert(Node *new_node)
Insert a new node into this AVL tree.
Definition avl_tree:227
Node * erase(Key_param_type key)
An alias for remove().
Definition avl_tree:165
Node * remove(Key_param_type key)
Remove the node with key from the tree.
Definition avl_tree:289
~Avl_tree() noexcept
Destroy the tree.
Definition avl_tree:171
Avl_tree()=default
Create an empty AVL tree.
Bst::Const_iterator Const_iterator
Constant forward iterator for the tree.
Definition avl_tree:139
Bst::Rev_iterator Rev_iterator
Backward iterator for the tree.
Definition avl_tree:141
Bst::Iterator Iterator
Definition avl_tree:137
Bst::Const_rev_iterator Const_rev_iterator
Constant backward iterator for the tree.
Definition avl_tree:143
Basic type of a node in a binary search tree (BST).
Definition bst_base.h:82
static Bst_node ** next_p(Bst_node *p, Direction d)
Get pointer to link in direction d.
Definition bst_base.h:106
static void rotate(Bst_node **t, Direction idir)
Rotate subtree t in the opposite direction of idir.
Definition bst_base.h:131
Bst_node()
Create uninitialized node.
Definition bst_base.h:123
static Bst_node * next(Bst_node const *p, Direction d)
Get next node in direction d.
Definition bst_base.h:98
Basic binary search tree (BST).
Definition bst.h:41
__Bst_iter< Node, Node const, Rev > Const_rev_iterator
Constant backward.
Definition bst.h:84
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_iter< Node, Node, Fwd > Iterator
Forward iterator.
Definition bst.h:78
Type_traits< Key_type >::Param_type Key_param_type
The type for key parameters.
Definition bst.h:68
Bst_node * _head
The head pointer of the tree.
Definition bst.h:98
__Bst_iter< Node, Node const, Fwd > Const_iterator
Constant forward iterator.
Definition bst.h:80
void remove_all(FUNC &&callback)
Clear the tree.
Definition bst.h:258
static Key_type k(Bst_node const *n)
Get the key value of n.
Definition bst.h:107
__Bst_iter< Node, Node, Rev > Rev_iterator
Backward iterator.
Definition bst.h:82
Our C++ library.
Definition arith:22
Pair implementation.
The direction to go in a binary search tree.
Definition bst_base.h:40
Pair of two values.
Definition pair:37