1 /* A typesafe wrapper around libiberty's splay-tree.h.
2 Copyright (C) 2015-2020 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify it under
7 the terms of the GNU General Public License as published by the Free
8 Software Foundation; either version 3, or (at your option) any later
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
20 #ifndef GCC_TYPED_SPLAY_TREE_H
21 #define GCC_TYPED_SPLAY_TREE_H
23 /* Typesafe wrapper around libiberty's splay-tree.h. */
24 template <typename KEY_TYPE
, typename VALUE_TYPE
>
25 class typed_splay_tree
28 typedef KEY_TYPE key_type
;
29 typedef VALUE_TYPE value_type
;
31 typedef int (*compare_fn
) (key_type
, key_type
);
32 typedef void (*delete_key_fn
) (key_type
);
33 typedef void (*delete_value_fn
) (value_type
);
34 typedef int (*foreach_fn
) (key_type
, value_type
, void *);
36 typed_splay_tree (compare_fn
,
41 value_type
lookup (key_type k
);
42 value_type
predecessor (key_type k
);
43 value_type
successor (key_type k
);
44 void insert (key_type k
, value_type v
);
45 void remove (key_type k
);
48 int foreach (foreach_fn
, void *);
51 /* Copy and assignment ops are not supported. */
52 typed_splay_tree (const typed_splay_tree
&);
53 typed_splay_tree
& operator = (const typed_splay_tree
&);
55 typedef key_type splay_tree_key
;
56 typedef value_type splay_tree_value
;
58 /* The nodes in the splay tree. */
59 struct splay_tree_node_s
{
64 splay_tree_value value
;
66 /* The left and right children, respectively. */
67 splay_tree_node_s
*left
, *right
;
69 /* Used as temporary value for tree traversals. */
70 splay_tree_node_s
*back
;
72 typedef splay_tree_node_s
*splay_tree_node
;
74 inline void KDEL (splay_tree_key
);
75 inline void VDEL (splay_tree_value
);
76 void splay_tree_delete_helper (splay_tree_node
);
77 static inline void rotate_left (splay_tree_node
*,
78 splay_tree_node
, splay_tree_node
);
79 static inline void rotate_right (splay_tree_node
*,
80 splay_tree_node
, splay_tree_node
);
81 void splay_tree_splay (splay_tree_key
);
82 static int splay_tree_foreach_helper (splay_tree_node
,
84 splay_tree_node
splay_tree_insert (splay_tree_key
, splay_tree_value
);
85 void splay_tree_remove (splay_tree_key key
);
86 splay_tree_node
splay_tree_lookup (splay_tree_key key
);
87 splay_tree_node
splay_tree_predecessor (splay_tree_key
);
88 splay_tree_node
splay_tree_successor (splay_tree_key
);
89 splay_tree_node
splay_tree_max ();
90 splay_tree_node
splay_tree_min ();
92 static value_type
node_to_value (splay_tree_node node
);
94 /* The root of the tree. */
97 /* The comparision function. */
100 /* The deallocate-key function. NULL if no cleanup is necessary. */
101 delete_key_fn delete_key
;
103 /* The deallocate-value function. NULL if no cleanup is necessary. */
104 delete_value_fn delete_value
;
107 /* Constructor for typed_splay_tree <K, V>. */
109 template <typename KEY_TYPE
, typename VALUE_TYPE
>
110 inline typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::
111 typed_splay_tree (compare_fn compare_fn
,
112 delete_key_fn delete_key_fn
,
113 delete_value_fn delete_value_fn
)
117 delete_key
= delete_key_fn
;
118 delete_value
= delete_value_fn
;
121 /* Destructor for typed_splay_tree <K, V>. */
123 template <typename KEY_TYPE
, typename VALUE_TYPE
>
124 inline typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::
127 splay_tree_delete_helper (root
);
130 /* Lookup KEY, returning a value if present, and NULL
133 template <typename KEY_TYPE
, typename VALUE_TYPE
>
135 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::lookup (key_type key
)
137 splay_tree_node node
= splay_tree_lookup (key
);
138 return node_to_value (node
);
141 /* Return the immediate predecessor of KEY, or NULL if there is no
142 predecessor. KEY need not be present in the tree. */
144 template <typename KEY_TYPE
, typename VALUE_TYPE
>
146 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::predecessor (key_type key
)
148 splay_tree_node node
= splay_tree_predecessor (key
);
149 return node_to_value (node
);
152 /* Return the immediate successor of KEY, or NULL if there is no
153 successor. KEY need not be present in the tree. */
155 template <typename KEY_TYPE
, typename VALUE_TYPE
>
157 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::successor (key_type key
)
159 splay_tree_node node
= splay_tree_successor (key
);
160 return node_to_value (node
);
163 /* Insert a new node (associating KEY with VALUE). If a
164 previous node with the indicated KEY exists, its data is replaced
165 with the new value. */
167 template <typename KEY_TYPE
, typename VALUE_TYPE
>
169 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::insert (key_type key
,
172 splay_tree_insert (key
, value
);
175 /* Remove a node (associating KEY with VALUE). */
177 template <typename KEY_TYPE
, typename VALUE_TYPE
>
179 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::remove (key_type key
)
181 splay_tree_remove (key
);
184 /* Get the value with maximal key. */
186 template <typename KEY_TYPE
, typename VALUE_TYPE
>
188 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::max ()
190 return node_to_value (splay_tree_max ());
193 /* Get the value with minimal key. */
195 template <typename KEY_TYPE
, typename VALUE_TYPE
>
197 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::min ()
199 return node_to_value (splay_tree_min ());
202 /* Call OUTER_CB, passing it the OUTER_USER_DATA, for every node,
203 following an in-order traversal. If OUTER_CB ever returns a non-zero
204 value, the iteration ceases immediately, and the value is returned.
205 Otherwise, this function returns 0. */
207 template <typename KEY_TYPE
, typename VALUE_TYPE
>
209 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::foreach (foreach_fn foreach_fn
,
212 return splay_tree_foreach_helper (root
, foreach_fn
, user_data
);
215 /* Internal function for converting from splay_tree_node to
217 template <typename KEY_TYPE
, typename VALUE_TYPE
>
219 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::node_to_value (splay_tree_node node
)
227 template <typename KEY_TYPE
, typename VALUE_TYPE
>
229 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::KDEL(splay_tree_key x
)
235 template <typename KEY_TYPE
, typename VALUE_TYPE
>
237 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::VDEL(splay_tree_value x
)
243 /* Deallocate NODE (a member of SP), and all its sub-trees. */
245 template <typename KEY_TYPE
, typename VALUE_TYPE
>
247 typed_splay_tree
<KEY_TYPE
,
248 VALUE_TYPE
>::splay_tree_delete_helper (splay_tree_node node
)
250 splay_tree_node pending
= NULL
;
251 splay_tree_node active
= NULL
;
259 /* We use the "back" field to hold the "next" pointer. */
260 node
->back
= pending
;
263 /* Now, keep processing the pending list until there aren't any
264 more. This is a little more complicated than just recursing, but
265 it doesn't toast the stack for large trees. */
273 splay_tree_node temp
;
275 /* active points to a node which has its key and value
276 deallocated, we just need to process left and right. */
280 KDEL (active
->left
->key
);
281 VDEL (active
->left
->value
);
282 active
->left
->back
= pending
;
283 pending
= active
->left
;
287 KDEL (active
->right
->key
);
288 VDEL (active
->right
->value
);
289 active
->right
->back
= pending
;
290 pending
= active
->right
;
300 /* Rotate the edge joining the left child N with its parent P. PP is the
301 grandparents' pointer to P. */
303 template <typename KEY_TYPE
, typename VALUE_TYPE
>
305 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::rotate_left (splay_tree_node
*pp
,
316 /* Rotate the edge joining the right child N with its parent P. PP is the
317 grandparents' pointer to P. */
319 template <typename KEY_TYPE
, typename VALUE_TYPE
>
321 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::rotate_right (splay_tree_node
*pp
,
332 /* Bottom up splay of key. */
334 template <typename KEY_TYPE
, typename VALUE_TYPE
>
336 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_splay (splay_tree_key key
)
343 splay_tree_node n
, c
;
346 cmp1
= (*comp
) (key
, n
->key
);
352 /* Left or right? If no child, then we're done. */
360 /* Next one left or right? If found or no child, we're done
361 after one rotation. */
362 cmp2
= (*comp
) (key
, c
->key
);
364 || (cmp2
< 0 && !c
->left
)
365 || (cmp2
> 0 && !c
->right
))
368 rotate_left (&root
, n
, c
);
370 rotate_right (&root
, n
, c
);
374 /* Now we have the four cases of double-rotation. */
375 if (cmp1
< 0 && cmp2
< 0)
377 rotate_left (&n
->left
, c
, c
->left
);
378 rotate_left (&root
, n
, n
->left
);
380 else if (cmp1
> 0 && cmp2
> 0)
382 rotate_right (&n
->right
, c
, c
->right
);
383 rotate_right (&root
, n
, n
->right
);
385 else if (cmp1
< 0 && cmp2
> 0)
387 rotate_right (&n
->left
, c
, c
->right
);
388 rotate_left (&root
, n
, n
->left
);
390 else if (cmp1
> 0 && cmp2
< 0)
392 rotate_left (&n
->right
, c
, c
->left
);
393 rotate_right (&root
, n
, n
->right
);
398 /* Call FN, passing it the DATA, for every node below NODE, all of
399 which are from SP, following an in-order traversal. If FN every
400 returns a non-zero value, the iteration ceases immediately, and the
401 value is returned. Otherwise, this function returns 0. */
403 template <typename KEY_TYPE
, typename VALUE_TYPE
>
405 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_foreach_helper (
406 splay_tree_node node
,
407 foreach_fn fn
, void *data
)
410 splay_tree_node stack
;
412 /* A non-recursive implementation is used to avoid filling the stack
413 for large trees. Splay trees are worst case O(n) in the depth of
434 val
= (*fn
) (node
->key
, node
->value
, data
);
444 /* Insert a new node (associating KEY with DATA) into SP. If a
445 previous node with the indicated KEY exists, its data is replaced
446 with the new value. Returns the new node. */
448 template <typename KEY_TYPE
, typename VALUE_TYPE
>
449 typename typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_node
450 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_insert (
452 splay_tree_value value
)
456 splay_tree_splay (key
);
459 comparison
= (*comp
)(root
->key
, key
);
461 if (root
&& comparison
== 0)
463 /* If the root of the tree already has the indicated KEY, just
464 replace the value with VALUE. */
470 /* Create a new node, and insert it at the root. */
471 splay_tree_node node
;
473 node
= new splay_tree_node_s
;
478 node
->left
= node
->right
= 0;
479 else if (comparison
< 0)
482 node
->right
= node
->left
->right
;
483 node
->left
->right
= 0;
488 node
->left
= node
->right
->left
;
489 node
->right
->left
= 0;
498 /* Remove KEY from SP. It is not an error if it did not exist. */
500 template <typename KEY_TYPE
, typename VALUE_TYPE
>
502 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_remove (splay_tree_key key
)
504 splay_tree_splay (key
);
506 if (root
&& (*comp
) (root
->key
, key
) == 0)
508 splay_tree_node left
, right
;
513 /* Delete the root node itself. */
517 /* One of the children is now the root. Doesn't matter much
518 which, so long as we preserve the properties of the tree. */
523 /* If there was a right child as well, hang it off the
524 right-most leaf of the left child. */
537 /* Lookup KEY in SP, returning VALUE if present, and NULL
540 template <typename KEY_TYPE
, typename VALUE_TYPE
>
541 typename typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_node
542 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_lookup (splay_tree_key key
)
544 splay_tree_splay (key
);
546 if (root
&& (*comp
)(root
->key
, key
) == 0)
552 /* Return the node in SP with the greatest key. */
554 template <typename KEY_TYPE
, typename VALUE_TYPE
>
555 typename typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_node
556 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_max ()
558 splay_tree_node n
= root
;
569 /* Return the node in SP with the smallest key. */
571 template <typename KEY_TYPE
, typename VALUE_TYPE
>
572 typename typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_node
573 typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_min ()
575 splay_tree_node n
= root
;
586 /* Return the immediate predecessor KEY, or NULL if there is no
587 predecessor. KEY need not be present in the tree. */
589 template <typename KEY_TYPE
, typename VALUE_TYPE
>
590 typename typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_node
591 typed_splay_tree
<KEY_TYPE
,
592 VALUE_TYPE
>::splay_tree_predecessor (splay_tree_key key
)
595 splay_tree_node node
;
597 /* If the tree is empty, there is certainly no predecessor. */
601 /* Splay the tree around KEY. That will leave either the KEY
602 itself, its predecessor, or its successor at the root. */
603 splay_tree_splay (key
);
604 comparison
= (*comp
)(root
->key
, key
);
606 /* If the predecessor is at the root, just return it. */
610 /* Otherwise, find the rightmost element of the left subtree. */
619 /* Return the immediate successor KEY, or NULL if there is no
620 successor. KEY need not be present in the tree. */
622 template <typename KEY_TYPE
, typename VALUE_TYPE
>
623 typename typed_splay_tree
<KEY_TYPE
, VALUE_TYPE
>::splay_tree_node
624 typed_splay_tree
<KEY_TYPE
,
625 VALUE_TYPE
>::splay_tree_successor (splay_tree_key key
)
628 splay_tree_node node
;
630 /* If the tree is empty, there is certainly no successor. */
634 /* Splay the tree around KEY. That will leave either the KEY
635 itself, its predecessor, or its successor at the root. */
636 splay_tree_splay (key
);
637 comparison
= (*comp
)(root
->key
, key
);
639 /* If the successor is at the root, just return it. */
643 /* Otherwise, find the leftmost element of the right subtree. */
652 #endif /* GCC_TYPED_SPLAY_TREE_H */