Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_splay_treeRk.H
Go to the documentation of this file.
1
2/*
3 Aleph_w
4
5 Data structures & Algorithms
6 version 2.0.0b
7 https://github.com/lrleon/Aleph-w
8
9 This file is part of Aleph-w library
10
11 Copyright (c) 2002-2026 Leandro Rabindranath Leon
12
13 Permission is hereby granted, free of charge, to any person obtaining a copy
14 of this software and associated documentation files (the "Software"), to deal
15 in the Software without restriction, including without limitation the rights
16 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17 copies of the Software, and to permit persons to whom the Software is
18 furnished to do so, subject to the following conditions:
19
20 The above copyright notice and this permission notice shall be included in all
21 copies or substantial portions of the Software.
22
23 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 SOFTWARE.
30*/
31
48# ifndef TPL_SPLAY_TREE_RK_H
49# define TPL_SPLAY_TREE_RK_H
50
51# include <tpl_binNodeXt.H>
52# include <ah-errors.H>
53
54using namespace Aleph;
55
56
106template <template <class> class NodeType, typename Key, class Compare>
108{
109public:
111
112private:
114 Compare cmp;
115 static constexpr signed char CmpLess = -1;
116 static constexpr signed char CmpEqual = 0;
117 static constexpr signed char CmpGreater = 1;
118
119 signed char splay_impl(const Key & key) noexcept
120 {
121 assert(root != Node::NullPtr); // splay requires non-empty tree
122 Node header(sentinelCtor);
123 Node * head_ptr = &header;
124 Node * l = head_ptr;
125 Node * r = head_ptr;
126 Node * t = root;
127
128 size_t l_size = 0;
129 size_t r_size = 0;
130 signed char cmp_result = CmpEqual;
131
132 while (true)
133 {
134 if (const Key & tk = KEY(t); cmp(key, tk)) // key < tk: go left
135 {
137 if (LLINK(t) == Node::NullPtr) [[unlikely]]
138 break;
139
140 if (cmp(key, KEY(LLINK(t)))) // zig-zig case
141 {
142 t = rotate_to_right_xt(t);
143 if (LLINK(t) == Node::NullPtr) [[unlikely]]
144 break;
145 }
146
147 LLINK(r) = t;
148 r = t;
149 t = LLINK(t);
150 r_size += 1 + COUNT(RLINK(r));
151 }
152 else if (cmp(tk, key)) // tk < key: go right
153 {
155 if (RLINK(t) == Node::NullPtr) [[unlikely]]
156 break;
157
158 if (cmp(KEY(RLINK(t)), key)) // zig-zig case
159 {
160 t = rotate_to_left_xt(t);
161 if (RLINK(t) == Node::NullPtr) [[unlikely]]
162 break;
163 }
164
165 RLINK(l) = t;
166 l = t;
167 t = RLINK(t);
168 l_size += 1 + COUNT(LLINK(l));
169 }
170 else [[unlikely]] // key == tk: found
171 {
173 break;
174 }
175 }
176
177 l_size += COUNT(LLINK(t));
178 r_size += COUNT(RLINK(t));
179 COUNT(t) = l_size + r_size + 1;
180
181 /* reassembling of subtrees in one with t as root */
182 RLINK(l) = LLINK(t);
183 LLINK(r) = RLINK(t);
184
185 LLINK(t) = RLINK(head_ptr);
186 RLINK(t) = LLINK(head_ptr);
187
188 for (Node * y = LLINK(t); y != Node::NullPtr; y = RLINK(y))
189 {
190 COUNT(y) = l_size;
191 l_size -= 1 + COUNT(LLINK(y));
192 }
193
194 for (Node * y = RLINK(t); y != Node::NullPtr; y = LLINK(y))
195 {
196 COUNT(y) = r_size;
197 r_size -= 1 + COUNT(RLINK(y));
198 }
199
200 root = t;
201
202 return cmp_result;
203 }
204
205public:
207 typedef Key key_type;
208
210 Compare &key_comp() { return cmp; }
211
213 Compare &get_compare() { return key_comp(); }
214
220 void splay(const Key & key) noexcept
221 {
222 (void) splay_impl(key);
223 }
224
226 GenTdSplayTreeRk(Compare __cmp = Compare())
227 : root(Node::NullPtr), cmp(__cmp)
228 {
229 // Empty
230 }
231
233 {
234 std::swap(root, tree.root);
235 std::swap(cmp, tree.cmp);
236 }
237
240 { /* empty */
241 }
242
243private:
245 {
246 COUNT(p) = COUNT(root) + 1;
247 const Key & pk = KEY(p);
248 const Key & rk = KEY(root);
249 if (cmp(pk, rk))
250 {
251 COUNT(root) -= COUNT(LLINK(root));
252 LLINK(p) = LLINK(root);
253 RLINK(p) = root;
254 LLINK(root) = Node::NullPtr;
255 }
256 else
257 {
258 COUNT(root) -= COUNT(RLINK(root));
259 RLINK(p) = RLINK(root);
260 LLINK(p) = root;
261 RLINK(root) = Node::NullPtr;
262 }
263
264 return root = p; // inserted node become root
265 }
266
267public:
275 {
276 assert(p != Node::NullPtr);
277 assert(COUNT(p) == 1);
278 assert(LLINK(p) == Node::NullPtr and RLINK(p) == Node::NullPtr);
279
280 /* test insertion in empty tree */
281 if (root == Node::NullPtr)
282 return root = p;
283
284 const Key & key = KEY(p);
285
286 const signed char cmp_result = splay_impl(key);
287 if (cmp_result == CmpEqual)
288 return nullptr; // item is already in tree
289
290 return __insert(p);
291 }
292
294 {
295 assert(p != Node::NullPtr);
296 assert(LLINK(p) == Node::NullPtr and RLINK(p) == Node::NullPtr);
297
298 /* test insertion in empty tree */
299 if (root == Node::NullPtr)
300 return root = p;
301
302 splay_impl(KEY(p));
303
304 return __insert(p);
305 }
306
314 Node * search(const Key & key)
315 {
316 if (root == Node::NullPtr)
317 return nullptr;
318
319 const signed char cmp_result = splay_impl(key);
320
321 return cmp_result == CmpEqual ? root : nullptr;
322 }
323
325 {
326 if (root == Node::NullPtr)
327 return root = p;
328
329 const Key & key = KEY(p);
330 const signed char cmp_result = splay_impl(key);
331 if (cmp_result == CmpEqual)
332 return root;
333
334 return __insert(p);
335 }
336
337private:
348 Node * splay_max(Node * r) noexcept
349 {
350 if (r == Node::NullPtr || RLINK(r) == Node::NullPtr)
351 return r;
352
353 Node header(sentinelCtor);
354 Node * head_ptr = &header;
355 Node * l = head_ptr;
356 Node * t = r;
357
358 size_t l_size = 0;
359
360 // Always go right to find maximum
361 while (RLINK(t) != Node::NullPtr)
362 {
363 // Zig-zig: if grandchild exists on the right, rotate twice
364 if (RLINK(RLINK(t)) != Node::NullPtr)
365 {
366 t = rotate_to_left_xt(t);
367 if (RLINK(t) == Node::NullPtr)
368 break;
369 }
370
371 // Link left: attach t to l's right
372 RLINK(l) = t;
373 l = t;
374 t = RLINK(t);
375 l_size += 1 + COUNT(LLINK(l));
376 }
377
378 // Reassemble
379 l_size += COUNT(LLINK(t));
380 COUNT(t) = l_size + 1;
381
382 RLINK(l) = LLINK(t);
383 LLINK(t) = RLINK(head_ptr);
384
385 // Recompute counts along the left spine
386 for (Node * y = LLINK(t); y != Node::NullPtr; y = RLINK(y))
387 {
388 COUNT(y) = l_size;
389 l_size -= 1 + COUNT(LLINK(y));
390 }
391
392 return t;
393 }
394
395public:
405 Node * remove(const Key & key)
406 {
407 if (root == Node::NullPtr)
408 return nullptr;
409
410 const signed char cmp_result = splay_impl(key);
411 if (cmp_result != CmpEqual)
412 return nullptr; /* key not found */
413
414 Node *ret_val = root; /* store node to delete */
415
416 if (LLINK(root) == Node::NullPtr)
417 root = RLINK(root);
418 else if (RLINK(root) == Node::NullPtr)
419 root = LLINK(root);
420 else
421 {
423
424 // Splay the maximum of left subtree to become root.
425 // We use splay_max() instead of splay(key) because splay(key) can
426 // bring a duplicate that is not the actual maximum, corrupting counts.
427 // splay_max() uses proper zig-zig rotations to maintain O(log n) amortized.
429
430 // The new root has no right child (it was the maximum)
431 // Connect the right subtree
434 }
435
436 ret_val->reset();
437
438 return ret_val;
439 }
440
443 {
444 return root;
445 }
446
447 bool verify() const { return check_rank_tree(root) and check_bst(root, cmp); }
448
450 size_t size() const
451 {
452 return COUNT(root);
453 }
454
456 bool is_empty() const
457 {
458 return root == Node::NullPtr;
459 }
460
472 std::pair<long, Node *> position(const Key & key)
473 {
474 if (root == Node::NullPtr)
475 return {-1, nullptr};
476
477 const signed char cmp_result = splay_impl(key);
478 if (cmp_result == CmpEqual)
479 return {static_cast<long>(COUNT(LLINK(root))), root};
480
481 return {-1, nullptr};
482 }
483
511 std::pair<long, Node *> find_position(const Key & key)
512 {
513 if (root == Node::NullPtr)
514 return {-1, nullptr};
515
516 const signed char cmp_result = splay_impl(key);
517 if (cmp_result == CmpEqual)
518 return {static_cast<long>(COUNT(LLINK(root))), root};
519
520 // key not found - determine position it would have
521 if (cmp_result == CmpLess)
522 return {static_cast<long>(COUNT(LLINK(root))) - 1, root}; // less than root
523 return {static_cast<long>(COUNT(LLINK(root))) + 1, root};
524 // greater than root
525 }
526
537 Node * select(const size_t & i)
538 {
539 return Aleph::select(root, i);
540 }
541
547 {
549 Node *curr = Node::NullPtr;
550 size_t pos = 0;
551
552 public:
553 Iterator() = default;
554
556 : tree_ptr(&tree), curr(Node::NullPtr), pos(0)
557 {
558 if (tree_ptr->root != Node::NullPtr)
560 }
561
562 bool has_curr() const noexcept { return curr != Node::NullPtr; }
563
564 Node * get_curr() const
565 {
566 ah_overflow_error_if(curr == Node::NullPtr)
567 << "Iterator is at end";
568 return curr;
569 }
570
572
573 void next()
574 {
575 ah_overflow_error_if(curr == Node::NullPtr)
576 << "Iterator is at end";
578 ++pos;
579 }
580
582 {
584 ++pos;
585 }
586
587 size_t get_pos() const noexcept { return pos; }
588
590 {
591 pos = 0;
592 if (tree_ptr != nullptr && tree_ptr->root != Node::NullPtr)
594 else
595 curr = Node::NullPtr;
596 }
597
598 private:
599 static Node * find_min(Node *r) noexcept
600 {
601 while (LLINK(r) != Node::NullPtr)
602 r = LLINK(r);
603 return r;
604 }
605
606 static Node * inorder_successor(Node *root, const Key & key) noexcept
607 {
608 Node *successor = Node::NullPtr;
609 Node *curr = root;
610
611 while (curr != Node::NullPtr)
612 {
613 if (key < KEY(curr))
614 {
615 successor = curr;
616 curr = LLINK(curr);
617 }
618 else
619 curr = RLINK(curr);
620 }
621
622 return successor;
623 }
624 };
625};
626
627
628template <typename Key, class Compare = Aleph::less<Key>>
629struct Splay_Tree_Rk : public GenTdSplayTreeRk<BinNodeXt, Key, Compare>
630{
632 using Base::Base;
633};
634
635
636template <typename Key, class Compare = Aleph::less<Key>>
637struct Splay_Tree_Rk_Vtl : public GenTdSplayTreeRk<BinNodeXtVtl, Key, Compare>
638{
640 using Base::Base;
641};
642
643
644#endif /* TPL_SPLAY_TREE_RK_H */
Exception handling system with formatted messages for Aleph-w.
#define ah_overflow_error_if(C)
Throws std::overflow_error if condition holds.
Definition ah-errors.H:463
@ sentinelCtor
Definition ahDefs.H:81
@ KEY
Definition btreepic.C:169
void reset() noexcept
Definition htlist.H:516
Inorder iterator over the extended splay tree.
size_t get_pos() const noexcept
Node * get_curr_ne() const noexcept
static Node * find_min(Node *r) noexcept
Iterator(GenTdSplayTreeRk &tree) noexcept
bool has_curr() const noexcept
static Node * inorder_successor(Node *root, const Key &key) noexcept
Top-down splay tree with rank support.
std::pair< long, Node * > position(const Key &key)
Returns the inorder (sorted) position of key.
Node * splay_max(Node *r) noexcept
Splay the maximum element to the root.
GenTdSplayTreeRk(Compare __cmp=Compare())
Constructor.
void splay(const Key &key) noexcept
search key within tree and splay that node.
Compare & get_compare()
static constexpr signed char CmpGreater
void swap(GenTdSplayTreeRk &tree)
std::pair< long, Node * > find_position(const Key &key)
Returns the inorder (sorted) position of key.
Node * insert(Node *p)
Inserts a node in a top down splay tree.
NodeType< Key > Node
Compare & key_comp()
Returns a reference to the comparison functor.
Node * remove(const Key &key)
Remove a key from a top-down splay tree.
Node * search_or_insert(Node *p)
bool is_empty() const
Returns true if the tree is empty.
signed char splay_impl(const Key &key) noexcept
Node * search(const Key &key)
Searches a key in a top down splay tree.
Node * __insert(Node *p)
static constexpr signed char CmpEqual
Key key_type
The key type stored in the node.
Node * select(const size_t &i)
Returns the node whose inorder position in the extended tree is i.
Node * insert_dup(Node *p)
virtual ~GenTdSplayTreeRk()
Destructor.
static constexpr signed char CmpLess
size_t size() const
Returns the number of nodes stored in the tree.
Node *& getRoot()
Get the top-down splay tree's root.
bool check_rank_tree(Node *root) noexcept
Return true if root is a valid extended binary tree.
bool check_bst(Node *p, const Compare &cmp=Compare())
Return true if p is a binary search tree.
constexpr Node *& RLINK(Node *p) noexcept
Return the right tree of p.
auto & COUNT(Node *p) noexcept
Return the number of nodes of the tree fron p is root.
Node * rotate_to_left_xt(Node *p) noexcept
Rotate to left the extended binary tree with root p.
Node * select(Node *r, const size_t pos)
Iterative selection of a node according to inorder position.
constexpr Node *& LLINK(Node *p) noexcept
Return a pointer to left subtree.
Node * rotate_to_right_xt(Node *p) noexcept
Rotate to right the extended bianry tree with root p
static mpfr_t y
Definition mpfr_mul_d.c:3
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
DynList< T > maps(const C &c, Op op)
Classic map operation.
Extended binary node with subtree count.
DynList< int > l