1 | /* A splay-tree datatype. |
2 | Copyright (C) 1998-2024 Free Software Foundation, Inc. |
3 | Contributed by Mark Mitchell (mark@markmitchell.com). |
4 | |
5 | This file is part of GNU CC. |
6 | |
7 | GNU CC is free software; you can redistribute it and/or modify it |
8 | under the terms of the GNU General Public License as published by |
9 | the Free Software Foundation; either version 2, or (at your option) |
10 | any later version. |
11 | |
12 | GNU CC is distributed in the hope that it will be useful, but |
13 | WITHOUT ANY WARRANTY; without even the implied warranty of |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
15 | General Public License for more details. |
16 | |
17 | You should have received a copy of the GNU General Public License |
18 | along with GNU CC; see the file COPYING. If not, write to |
19 | the Free Software Foundation, 51 Franklin Street - Fifth Floor, |
20 | Boston, MA 02110-1301, USA. */ |
21 | |
22 | /* For an easily readable description of splay-trees, see: |
23 | |
24 | Lewis, Harry R. and Denenberg, Larry. Data Structures and Their |
25 | Algorithms. Harper-Collins, Inc. 1991. */ |
26 | |
27 | #ifdef HAVE_CONFIG_H |
28 | #include "config.h" |
29 | #endif |
30 | |
31 | #ifdef HAVE_STDLIB_H |
32 | #include <stdlib.h> |
33 | #endif |
34 | #ifdef HAVE_STRING_H |
35 | #include <string.h> |
36 | #endif |
37 | |
38 | #include <stdio.h> |
39 | |
40 | #include "libiberty.h" |
41 | #include "splay-tree.h" |
42 | |
43 | static void splay_tree_delete_helper (splay_tree, splay_tree_node); |
44 | static inline void rotate_left (splay_tree_node *, |
45 | splay_tree_node, splay_tree_node); |
46 | static inline void rotate_right (splay_tree_node *, |
47 | splay_tree_node, splay_tree_node); |
48 | static void splay_tree_splay (splay_tree, splay_tree_key); |
49 | static int splay_tree_foreach_helper (splay_tree_node, |
50 | splay_tree_foreach_fn, void*); |
51 | |
52 | /* Deallocate NODE (a member of SP), and all its sub-trees. */ |
53 | |
54 | static void |
55 | splay_tree_delete_helper (splay_tree sp, splay_tree_node node) |
56 | { |
57 | splay_tree_node pending = 0; |
58 | splay_tree_node active = 0; |
59 | |
60 | if (!node) |
61 | return; |
62 | |
63 | #define KDEL(x) if (sp->delete_key) (*sp->delete_key)(x); |
64 | #define VDEL(x) if (sp->delete_value) (*sp->delete_value)(x); |
65 | |
66 | KDEL (node->key); |
67 | VDEL (node->value); |
68 | |
69 | /* We use the "key" field to hold the "next" pointer. */ |
70 | node->key = (splay_tree_key)pending; |
71 | pending = (splay_tree_node)node; |
72 | |
73 | /* Now, keep processing the pending list until there aren't any |
74 | more. This is a little more complicated than just recursing, but |
75 | it doesn't toast the stack for large trees. */ |
76 | |
77 | while (pending) |
78 | { |
79 | active = pending; |
80 | pending = 0; |
81 | while (active) |
82 | { |
83 | splay_tree_node temp; |
84 | |
85 | /* active points to a node which has its key and value |
86 | deallocated, we just need to process left and right. */ |
87 | |
88 | if (active->left) |
89 | { |
90 | KDEL (active->left->key); |
91 | VDEL (active->left->value); |
92 | active->left->key = (splay_tree_key)pending; |
93 | pending = (splay_tree_node)(active->left); |
94 | } |
95 | if (active->right) |
96 | { |
97 | KDEL (active->right->key); |
98 | VDEL (active->right->value); |
99 | active->right->key = (splay_tree_key)pending; |
100 | pending = (splay_tree_node)(active->right); |
101 | } |
102 | |
103 | temp = active; |
104 | active = (splay_tree_node)(temp->key); |
105 | (*sp->deallocate) ((char*) temp, sp->allocate_data); |
106 | } |
107 | } |
108 | #undef KDEL |
109 | #undef VDEL |
110 | } |
111 | |
112 | /* Rotate the edge joining the left child N with its parent P. PP is the |
113 | grandparents' pointer to P. */ |
114 | |
115 | static inline void |
116 | rotate_left (splay_tree_node *pp, splay_tree_node p, splay_tree_node n) |
117 | { |
118 | splay_tree_node tmp; |
119 | tmp = n->right; |
120 | n->right = p; |
121 | p->left = tmp; |
122 | *pp = n; |
123 | } |
124 | |
125 | /* Rotate the edge joining the right child N with its parent P. PP is the |
126 | grandparents' pointer to P. */ |
127 | |
128 | static inline void |
129 | rotate_right (splay_tree_node *pp, splay_tree_node p, splay_tree_node n) |
130 | { |
131 | splay_tree_node tmp; |
132 | tmp = n->left; |
133 | n->left = p; |
134 | p->right = tmp; |
135 | *pp = n; |
136 | } |
137 | |
138 | /* Bottom up splay of key. */ |
139 | |
140 | static void |
141 | splay_tree_splay (splay_tree sp, splay_tree_key key) |
142 | { |
143 | if (sp->root == 0) |
144 | return; |
145 | |
146 | do { |
147 | int cmp1, cmp2; |
148 | splay_tree_node n, c; |
149 | |
150 | n = sp->root; |
151 | cmp1 = (*sp->comp) (key, n->key); |
152 | |
153 | /* Found. */ |
154 | if (cmp1 == 0) |
155 | return; |
156 | |
157 | /* Left or right? If no child, then we're done. */ |
158 | if (cmp1 < 0) |
159 | c = n->left; |
160 | else |
161 | c = n->right; |
162 | if (!c) |
163 | return; |
164 | |
165 | /* Next one left or right? If found or no child, we're done |
166 | after one rotation. */ |
167 | cmp2 = (*sp->comp) (key, c->key); |
168 | if (cmp2 == 0 |
169 | || (cmp2 < 0 && !c->left) |
170 | || (cmp2 > 0 && !c->right)) |
171 | { |
172 | if (cmp1 < 0) |
173 | rotate_left (pp: &sp->root, p: n, n: c); |
174 | else |
175 | rotate_right (pp: &sp->root, p: n, n: c); |
176 | return; |
177 | } |
178 | |
179 | /* Now we have the four cases of double-rotation. */ |
180 | if (cmp1 < 0 && cmp2 < 0) |
181 | { |
182 | rotate_left (pp: &n->left, p: c, n: c->left); |
183 | rotate_left (pp: &sp->root, p: n, n: n->left); |
184 | } |
185 | else if (cmp1 > 0 && cmp2 > 0) |
186 | { |
187 | rotate_right (pp: &n->right, p: c, n: c->right); |
188 | rotate_right (pp: &sp->root, p: n, n: n->right); |
189 | } |
190 | else if (cmp1 < 0 && cmp2 > 0) |
191 | { |
192 | rotate_right (pp: &n->left, p: c, n: c->right); |
193 | rotate_left (pp: &sp->root, p: n, n: n->left); |
194 | } |
195 | else if (cmp1 > 0 && cmp2 < 0) |
196 | { |
197 | rotate_left (pp: &n->right, p: c, n: c->left); |
198 | rotate_right (pp: &sp->root, p: n, n: n->right); |
199 | } |
200 | } while (1); |
201 | } |
202 | |
203 | /* Call FN, passing it the DATA, for every node below NODE, all of |
204 | which are from SP, following an in-order traversal. If FN every |
205 | returns a non-zero value, the iteration ceases immediately, and the |
206 | value is returned. Otherwise, this function returns 0. */ |
207 | |
208 | static int |
209 | splay_tree_foreach_helper (splay_tree_node node, |
210 | splay_tree_foreach_fn fn, void *data) |
211 | { |
212 | int val; |
213 | splay_tree_node *stack; |
214 | int stack_ptr, stack_size; |
215 | |
216 | /* A non-recursive implementation is used to avoid filling the stack |
217 | for large trees. Splay trees are worst case O(n) in the depth of |
218 | the tree. */ |
219 | |
220 | #define INITIAL_STACK_SIZE 100 |
221 | stack_size = INITIAL_STACK_SIZE; |
222 | stack_ptr = 0; |
223 | stack = XNEWVEC (splay_tree_node, stack_size); |
224 | val = 0; |
225 | |
226 | for (;;) |
227 | { |
228 | while (node != NULL) |
229 | { |
230 | if (stack_ptr == stack_size) |
231 | { |
232 | stack_size *= 2; |
233 | stack = XRESIZEVEC (splay_tree_node, stack, stack_size); |
234 | } |
235 | stack[stack_ptr++] = node; |
236 | node = node->left; |
237 | } |
238 | |
239 | if (stack_ptr == 0) |
240 | break; |
241 | |
242 | node = stack[--stack_ptr]; |
243 | |
244 | val = (*fn) (node, data); |
245 | if (val) |
246 | break; |
247 | |
248 | node = node->right; |
249 | } |
250 | |
251 | XDELETEVEC (stack); |
252 | return val; |
253 | } |
254 | |
255 | /* An allocator and deallocator based on xmalloc. */ |
256 | static void * |
257 | splay_tree_xmalloc_allocate (int size, void *data ATTRIBUTE_UNUSED) |
258 | { |
259 | return (void *) xmalloc (size); |
260 | } |
261 | |
262 | static void |
263 | splay_tree_xmalloc_deallocate (void *object, void *data ATTRIBUTE_UNUSED) |
264 | { |
265 | free (ptr: object); |
266 | } |
267 | |
268 | |
269 | /* Allocate a new splay tree, using COMPARE_FN to compare nodes, |
270 | DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate |
271 | values. Use xmalloc to allocate the splay tree structure, and any |
272 | nodes added. */ |
273 | |
274 | splay_tree |
275 | splay_tree_new (splay_tree_compare_fn compare_fn, |
276 | splay_tree_delete_key_fn delete_key_fn, |
277 | splay_tree_delete_value_fn delete_value_fn) |
278 | { |
279 | return (splay_tree_new_with_allocator |
280 | (compare_fn, delete_key_fn, delete_value_fn, |
281 | splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate, 0)); |
282 | } |
283 | |
284 | |
285 | /* Allocate a new splay tree, using COMPARE_FN to compare nodes, |
286 | DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate |
287 | values. */ |
288 | |
289 | splay_tree |
290 | splay_tree_new_with_allocator (splay_tree_compare_fn compare_fn, |
291 | splay_tree_delete_key_fn delete_key_fn, |
292 | splay_tree_delete_value_fn delete_value_fn, |
293 | splay_tree_allocate_fn allocate_fn, |
294 | splay_tree_deallocate_fn deallocate_fn, |
295 | void *allocate_data) |
296 | { |
297 | return |
298 | splay_tree_new_typed_alloc (compare_fn, delete_key_fn, delete_value_fn, |
299 | allocate_fn, allocate_fn, deallocate_fn, |
300 | allocate_data); |
301 | } |
302 | |
303 | /* |
304 | |
305 | @deftypefn Supplemental splay_tree splay_tree_new_with_typed_alloc @ |
306 | (splay_tree_compare_fn @var{compare_fn}, @ |
307 | splay_tree_delete_key_fn @var{delete_key_fn}, @ |
308 | splay_tree_delete_value_fn @var{delete_value_fn}, @ |
309 | splay_tree_allocate_fn @var{tree_allocate_fn}, @ |
310 | splay_tree_allocate_fn @var{node_allocate_fn}, @ |
311 | splay_tree_deallocate_fn @var{deallocate_fn}, @ |
312 | void * @var{allocate_data}) |
313 | |
314 | This function creates a splay tree that uses two different allocators |
315 | @var{tree_allocate_fn} and @var{node_allocate_fn} to use for allocating the |
316 | tree itself and its nodes respectively. This is useful when variables of |
317 | different types need to be allocated with different allocators. |
318 | |
319 | The splay tree will use @var{compare_fn} to compare nodes, |
320 | @var{delete_key_fn} to deallocate keys, and @var{delete_value_fn} to |
321 | deallocate values. Keys and values will be deallocated when the |
322 | tree is deleted using splay_tree_delete or when a node is removed |
323 | using splay_tree_remove. splay_tree_insert will release the previously |
324 | inserted key and value using @var{delete_key_fn} and @var{delete_value_fn} |
325 | if the inserted key is already found in the tree. |
326 | |
327 | @end deftypefn |
328 | |
329 | */ |
330 | |
331 | splay_tree |
332 | splay_tree_new_typed_alloc (splay_tree_compare_fn compare_fn, |
333 | splay_tree_delete_key_fn delete_key_fn, |
334 | splay_tree_delete_value_fn delete_value_fn, |
335 | splay_tree_allocate_fn tree_allocate_fn, |
336 | splay_tree_allocate_fn node_allocate_fn, |
337 | splay_tree_deallocate_fn deallocate_fn, |
338 | void * allocate_data) |
339 | { |
340 | splay_tree sp = (splay_tree) (*tree_allocate_fn) |
341 | (sizeof (struct splay_tree_s), allocate_data); |
342 | |
343 | sp->root = 0; |
344 | sp->comp = compare_fn; |
345 | sp->delete_key = delete_key_fn; |
346 | sp->delete_value = delete_value_fn; |
347 | sp->allocate = node_allocate_fn; |
348 | sp->deallocate = deallocate_fn; |
349 | sp->allocate_data = allocate_data; |
350 | |
351 | return sp; |
352 | } |
353 | |
354 | /* Deallocate SP. */ |
355 | |
356 | void |
357 | splay_tree_delete (splay_tree sp) |
358 | { |
359 | splay_tree_delete_helper (sp, node: sp->root); |
360 | (*sp->deallocate) ((char*) sp, sp->allocate_data); |
361 | } |
362 | |
363 | /* Insert a new node (associating KEY with DATA) into SP. If a |
364 | previous node with the indicated KEY exists, its data is replaced |
365 | with the new value. Returns the new node. */ |
366 | |
367 | splay_tree_node |
368 | splay_tree_insert (splay_tree sp, splay_tree_key key, splay_tree_value value) |
369 | { |
370 | int comparison = 0; |
371 | |
372 | splay_tree_splay (sp, key); |
373 | |
374 | if (sp->root) |
375 | comparison = (*sp->comp)(sp->root->key, key); |
376 | |
377 | if (sp->root && comparison == 0) |
378 | { |
379 | /* If the root of the tree already has the indicated KEY, delete |
380 | the old key and old value, and replace them with KEY and VALUE. */ |
381 | if (sp->delete_key) |
382 | (*sp->delete_key) (sp->root->key); |
383 | if (sp->delete_value) |
384 | (*sp->delete_value)(sp->root->value); |
385 | sp->root->key = key; |
386 | sp->root->value = value; |
387 | } |
388 | else |
389 | { |
390 | /* Create a new node, and insert it at the root. */ |
391 | splay_tree_node node; |
392 | |
393 | node = ((splay_tree_node) |
394 | (*sp->allocate) (sizeof (struct splay_tree_node_s), |
395 | sp->allocate_data)); |
396 | node->key = key; |
397 | node->value = value; |
398 | |
399 | if (!sp->root) |
400 | node->left = node->right = 0; |
401 | else if (comparison < 0) |
402 | { |
403 | node->left = sp->root; |
404 | node->right = node->left->right; |
405 | node->left->right = 0; |
406 | } |
407 | else |
408 | { |
409 | node->right = sp->root; |
410 | node->left = node->right->left; |
411 | node->right->left = 0; |
412 | } |
413 | |
414 | sp->root = node; |
415 | } |
416 | |
417 | return sp->root; |
418 | } |
419 | |
420 | /* Remove KEY from SP. It is not an error if it did not exist. */ |
421 | |
422 | void |
423 | splay_tree_remove (splay_tree sp, splay_tree_key key) |
424 | { |
425 | splay_tree_splay (sp, key); |
426 | |
427 | if (sp->root && (*sp->comp) (sp->root->key, key) == 0) |
428 | { |
429 | splay_tree_node left, right; |
430 | |
431 | left = sp->root->left; |
432 | right = sp->root->right; |
433 | |
434 | /* Delete the root node itself. */ |
435 | if (sp->delete_key) |
436 | (*sp->delete_key) (sp->root->key); |
437 | if (sp->delete_value) |
438 | (*sp->delete_value) (sp->root->value); |
439 | (*sp->deallocate) (sp->root, sp->allocate_data); |
440 | |
441 | /* One of the children is now the root. Doesn't matter much |
442 | which, so long as we preserve the properties of the tree. */ |
443 | if (left) |
444 | { |
445 | sp->root = left; |
446 | |
447 | /* If there was a right child as well, hang it off the |
448 | right-most leaf of the left child. */ |
449 | if (right) |
450 | { |
451 | while (left->right) |
452 | left = left->right; |
453 | left->right = right; |
454 | } |
455 | } |
456 | else |
457 | sp->root = right; |
458 | } |
459 | } |
460 | |
461 | /* Lookup KEY in SP, returning VALUE if present, and NULL |
462 | otherwise. */ |
463 | |
464 | splay_tree_node |
465 | splay_tree_lookup (splay_tree sp, splay_tree_key key) |
466 | { |
467 | splay_tree_splay (sp, key); |
468 | |
469 | if (sp->root && (*sp->comp)(sp->root->key, key) == 0) |
470 | return sp->root; |
471 | else |
472 | return 0; |
473 | } |
474 | |
475 | /* Return the node in SP with the greatest key. */ |
476 | |
477 | splay_tree_node |
478 | splay_tree_max (splay_tree sp) |
479 | { |
480 | splay_tree_node n = sp->root; |
481 | |
482 | if (!n) |
483 | return NULL; |
484 | |
485 | while (n->right) |
486 | n = n->right; |
487 | |
488 | return n; |
489 | } |
490 | |
491 | /* Return the node in SP with the smallest key. */ |
492 | |
493 | splay_tree_node |
494 | splay_tree_min (splay_tree sp) |
495 | { |
496 | splay_tree_node n = sp->root; |
497 | |
498 | if (!n) |
499 | return NULL; |
500 | |
501 | while (n->left) |
502 | n = n->left; |
503 | |
504 | return n; |
505 | } |
506 | |
507 | /* Return the immediate predecessor KEY, or NULL if there is no |
508 | predecessor. KEY need not be present in the tree. */ |
509 | |
510 | splay_tree_node |
511 | splay_tree_predecessor (splay_tree sp, splay_tree_key key) |
512 | { |
513 | int comparison; |
514 | splay_tree_node node; |
515 | |
516 | /* If the tree is empty, there is certainly no predecessor. */ |
517 | if (!sp->root) |
518 | return NULL; |
519 | |
520 | /* Splay the tree around KEY. That will leave either the KEY |
521 | itself, its predecessor, or its successor at the root. */ |
522 | splay_tree_splay (sp, key); |
523 | comparison = (*sp->comp)(sp->root->key, key); |
524 | |
525 | /* If the predecessor is at the root, just return it. */ |
526 | if (comparison < 0) |
527 | return sp->root; |
528 | |
529 | /* Otherwise, find the rightmost element of the left subtree. */ |
530 | node = sp->root->left; |
531 | if (node) |
532 | while (node->right) |
533 | node = node->right; |
534 | |
535 | return node; |
536 | } |
537 | |
538 | /* Return the immediate successor KEY, or NULL if there is no |
539 | successor. KEY need not be present in the tree. */ |
540 | |
541 | splay_tree_node |
542 | splay_tree_successor (splay_tree sp, splay_tree_key key) |
543 | { |
544 | int comparison; |
545 | splay_tree_node node; |
546 | |
547 | /* If the tree is empty, there is certainly no successor. */ |
548 | if (!sp->root) |
549 | return NULL; |
550 | |
551 | /* Splay the tree around KEY. That will leave either the KEY |
552 | itself, its predecessor, or its successor at the root. */ |
553 | splay_tree_splay (sp, key); |
554 | comparison = (*sp->comp)(sp->root->key, key); |
555 | |
556 | /* If the successor is at the root, just return it. */ |
557 | if (comparison > 0) |
558 | return sp->root; |
559 | |
560 | /* Otherwise, find the leftmost element of the right subtree. */ |
561 | node = sp->root->right; |
562 | if (node) |
563 | while (node->left) |
564 | node = node->left; |
565 | |
566 | return node; |
567 | } |
568 | |
569 | /* Call FN, passing it the DATA, for every node in SP, following an |
570 | in-order traversal. If FN every returns a non-zero value, the |
571 | iteration ceases immediately, and the value is returned. |
572 | Otherwise, this function returns 0. */ |
573 | |
574 | int |
575 | splay_tree_foreach (splay_tree sp, splay_tree_foreach_fn fn, void *data) |
576 | { |
577 | return splay_tree_foreach_helper (node: sp->root, fn, data); |
578 | } |
579 | |
580 | /* Splay-tree comparison function, treating the keys as ints. */ |
581 | |
582 | int |
583 | splay_tree_compare_ints (splay_tree_key k1, splay_tree_key k2) |
584 | { |
585 | if ((int) k1 < (int) k2) |
586 | return -1; |
587 | else if ((int) k1 > (int) k2) |
588 | return 1; |
589 | else |
590 | return 0; |
591 | } |
592 | |
593 | /* Splay-tree comparison function, treating the keys as pointers. */ |
594 | |
595 | int |
596 | splay_tree_compare_pointers (splay_tree_key k1, splay_tree_key k2) |
597 | { |
598 | if ((char*) k1 < (char*) k2) |
599 | return -1; |
600 | else if ((char*) k1 > (char*) k2) |
601 | return 1; |
602 | else |
603 | return 0; |
604 | } |
605 | |
606 | /* Splay-tree comparison function, treating the keys as strings. */ |
607 | |
608 | int |
609 | splay_tree_compare_strings (splay_tree_key k1, splay_tree_key k2) |
610 | { |
611 | return strcmp (s1: (char *) k1, s2: (char *) k2); |
612 | } |
613 | |
614 | /* Splay-tree delete function, simply using free. */ |
615 | |
616 | void |
617 | splay_tree_delete_pointers (splay_tree_value value) |
618 | { |
619 | free (ptr: (void *) value); |
620 | } |
621 | |