1 /* A splay-tree datatype.
2 Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
3 Contributed by Mark Mitchell (mark@markmitchell.com).
5 This file is part of GNU CC.
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)
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.
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. */
22 /* For an easily readable description of splay-trees, see:
24 Lewis, Harry R. and Denenberg, Larry. Data Structures and Their
25 Algorithms. Harper-Collins, Inc. 1991. */
30 #include "magic_splay_tree.h"
33 #define xmalloc malloc
36 static void splay_tree_delete_helper (splay_tree
, splay_tree_node
);
37 static inline void rotate_left (splay_tree_node
*,
38 splay_tree_node
, splay_tree_node
);
39 static inline void rotate_right (splay_tree_node
*,
40 splay_tree_node
, splay_tree_node
);
41 static void splay_tree_splay (splay_tree
, splay_tree_key
);
42 static int splay_tree_foreach_helper (splay_tree
, splay_tree_node
,
43 splay_tree_foreach_fn
, void*);
45 /* Deallocate NODE (a member of SP), and all its sub-trees. */
48 splay_tree_delete_helper (splay_tree sp
, splay_tree_node node
)
50 splay_tree_node pending
= 0;
51 splay_tree_node active
= 0;
56 #define KDEL(x) if (sp->delete_key) (*sp->delete_key)(x);
57 #define VDEL(x) if (sp->delete_value) (*sp->delete_value)(x);
62 /* We use the "key" field to hold the "next" pointer. */
63 node
->key
= (splay_tree_key
)pending
;
64 pending
= (splay_tree_node
)node
;
66 /* Now, keep processing the pending list until there aren't any
67 more. This is a little more complicated than just recursing, but
68 it doesn't toast the stack for large trees. */
78 /* active points to a node which has its key and value
79 deallocated, we just need to process left and right. */
83 KDEL (active
->left
->key
);
84 VDEL (active
->left
->value
);
85 active
->left
->key
= (splay_tree_key
)pending
;
86 pending
= (splay_tree_node
)(active
->left
);
90 KDEL (active
->right
->key
);
91 VDEL (active
->right
->value
);
92 active
->right
->key
= (splay_tree_key
)pending
;
93 pending
= (splay_tree_node
)(active
->right
);
97 active
= (splay_tree_node
)(temp
->key
);
98 (*sp
->deallocate
) ((char*) temp
, sp
->allocate_data
);
105 /* Rotate the edge joining the left child N with its parent P. PP is the
106 grandparents pointer to P. */
109 rotate_left (splay_tree_node
*pp
, splay_tree_node p
, splay_tree_node n
)
118 /* Rotate the edge joining the right child N with its parent P. PP is the
119 grandparents pointer to P. */
122 rotate_right (splay_tree_node
*pp
, splay_tree_node p
, splay_tree_node n
)
131 /* Bottom up splay of key. */
134 splay_tree_splay (splay_tree sp
, splay_tree_key key
)
141 splay_tree_node n
, c
;
144 cmp1
= (*sp
->comp
) (key
, n
->key
);
150 /* Left or right? If no child, then we're done. */
158 /* Next one left or right? If found or no child, we're done
159 after one rotation. */
160 cmp2
= (*sp
->comp
) (key
, c
->key
);
162 || (cmp2
< 0 && !c
->left
)
163 || (cmp2
> 0 && !c
->right
))
166 rotate_left (&sp
->root
, n
, c
);
168 rotate_right (&sp
->root
, n
, c
);
172 /* Now we have the four cases of double-rotation. */
173 if (cmp1
< 0 && cmp2
< 0)
175 rotate_left (&n
->left
, c
, c
->left
);
176 rotate_left (&sp
->root
, n
, n
->left
);
178 else if (cmp1
> 0 && cmp2
> 0)
180 rotate_right (&n
->right
, c
, c
->right
);
181 rotate_right (&sp
->root
, n
, n
->right
);
183 else if (cmp1
< 0 && cmp2
> 0)
185 rotate_right (&n
->left
, c
, c
->right
);
186 rotate_left (&sp
->root
, n
, n
->left
);
188 else if (cmp1
> 0 && cmp2
< 0)
190 rotate_left (&n
->right
, c
, c
->left
);
191 rotate_right (&sp
->root
, n
, n
->right
);
196 /* Call FN, passing it the DATA, for every node below NODE, all of
197 which are from SP, following an in-order traversal. If FN every
198 returns a non-zero value, the iteration ceases immediately, and the
199 value is returned. Otherwise, this function returns 0. */
202 splay_tree_foreach_helper (splay_tree sp
, splay_tree_node node
,
203 splay_tree_foreach_fn fn
, void *data
)
210 val
= splay_tree_foreach_helper (sp
, node
->left
, fn
, data
);
214 val
= (*fn
)(node
, data
);
218 return splay_tree_foreach_helper (sp
, node
->right
, fn
, data
);
222 /* An allocator and deallocator based on xmalloc. */
224 splay_tree_xmalloc_allocate (int size
, void *data ATTRIBUTE_UNUSED
)
226 return (void *) xmalloc (size
);
230 splay_tree_xmalloc_deallocate (void *object
, void *data ATTRIBUTE_UNUSED
)
236 /* Allocate a new splay tree, using COMPARE_FN to compare nodes,
237 DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
238 values. Use xmalloc to allocate the splay tree structure, and any
242 splay_tree_new (splay_tree_compare_fn compare_fn
,
243 splay_tree_delete_key_fn delete_key_fn
,
244 splay_tree_delete_value_fn delete_value_fn
)
246 return (splay_tree_new_with_allocator
247 (compare_fn
, delete_key_fn
, delete_value_fn
,
248 splay_tree_xmalloc_allocate
, splay_tree_xmalloc_deallocate
, 0));
252 /* Allocate a new splay tree, using COMPARE_FN to compare nodes,
253 DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
257 splay_tree_new_with_allocator (splay_tree_compare_fn compare_fn
,
258 splay_tree_delete_key_fn delete_key_fn
,
259 splay_tree_delete_value_fn delete_value_fn
,
260 splay_tree_allocate_fn allocate_fn
,
261 splay_tree_deallocate_fn deallocate_fn
,
264 splay_tree sp
= (splay_tree
) (*allocate_fn
) (sizeof (struct splay_tree_s
),
267 sp
->comp
= compare_fn
;
268 sp
->delete_key
= delete_key_fn
;
269 sp
->delete_value
= delete_value_fn
;
270 sp
->allocate
= allocate_fn
;
271 sp
->deallocate
= deallocate_fn
;
272 sp
->allocate_data
= allocate_data
;
280 splay_tree_delete (splay_tree sp
)
282 splay_tree_delete_helper (sp
, sp
->root
);
283 (*sp
->deallocate
) ((char*) sp
, sp
->allocate_data
);
286 /* Insert a new node (associating KEY with DATA) into SP. If a
287 previous node with the indicated KEY exists, its data is replaced
288 with the new value. Returns the new node. */
291 splay_tree_insert (splay_tree sp
, splay_tree_key key
, splay_tree_value value
)
295 splay_tree_splay (sp
, key
);
298 comparison
= (*sp
->comp
)(sp
->root
->key
, key
);
300 if (sp
->root
&& comparison
== 0)
302 /* If the root of the tree already has the indicated KEY, just
303 replace the value with VALUE. */
304 if (sp
->delete_value
)
305 (*sp
->delete_value
)(sp
->root
->value
);
306 sp
->root
->value
= value
;
310 /* Create a new node, and insert it at the root. */
311 splay_tree_node node
;
313 node
= ((splay_tree_node
)
314 (*sp
->allocate
) (sizeof (struct splay_tree_node_s
),
320 node
->left
= node
->right
= 0;
321 else if (comparison
< 0)
323 node
->left
= sp
->root
;
324 node
->right
= node
->left
->right
;
325 node
->left
->right
= 0;
329 node
->right
= sp
->root
;
330 node
->left
= node
->right
->left
;
331 node
->right
->left
= 0;
340 /* Remove KEY from SP. It is not an error if it did not exist. */
343 splay_tree_remove (splay_tree sp
, splay_tree_key key
)
345 splay_tree_splay (sp
, key
);
347 if (sp
->root
&& (*sp
->comp
) (sp
->root
->key
, key
) == 0)
349 splay_tree_node left
, right
;
351 left
= sp
->root
->left
;
352 right
= sp
->root
->right
;
354 /* Delete the root node itself. */
355 if (sp
->delete_value
)
356 (*sp
->delete_value
) (sp
->root
->value
);
357 (*sp
->deallocate
) (sp
->root
, sp
->allocate_data
);
359 /* One of the children is now the root. Doesn't matter much
360 which, so long as we preserve the properties of the tree. */
365 /* If there was a right child as well, hang it off the
366 right-most leaf of the left child. */
379 /* Lookup KEY in SP, returning VALUE if present, and NULL
383 splay_tree_lookup (splay_tree sp
, splay_tree_key key
)
385 splay_tree_splay (sp
, key
);
387 if (sp
->root
&& (*sp
->comp
)(sp
->root
->key
, key
) == 0)
393 /* Return the node in SP with the greatest key. */
396 splay_tree_max (splay_tree sp
)
398 splay_tree_node n
= sp
->root
;
409 /* Return the node in SP with the smallest key. */
412 splay_tree_min (splay_tree sp
)
414 splay_tree_node n
= sp
->root
;
425 /* Return the immediate predecessor KEY, or NULL if there is no
426 predecessor. KEY need not be present in the tree. */
429 splay_tree_predecessor (splay_tree sp
, splay_tree_key key
)
432 splay_tree_node node
;
434 /* If the tree is empty, there is certainly no predecessor. */
438 /* Splay the tree around KEY. That will leave either the KEY
439 itself, its predecessor, or its successor at the root. */
440 splay_tree_splay (sp
, key
);
441 comparison
= (*sp
->comp
)(sp
->root
->key
, key
);
443 /* If the predecessor is at the root, just return it. */
447 /* Otherwise, find the rightmost element of the left subtree. */
448 node
= sp
->root
->left
;
456 /* Return the immediate successor KEY, or NULL if there is no
457 successor. KEY need not be present in the tree. */
460 splay_tree_successor (splay_tree sp
, splay_tree_key key
)
463 splay_tree_node node
;
465 /* If the tree is empty, there is certainly no successor. */
469 /* Splay the tree around KEY. That will leave either the KEY
470 itself, its predecessor, or its successor at the root. */
471 splay_tree_splay (sp
, key
);
472 comparison
= (*sp
->comp
)(sp
->root
->key
, key
);
474 /* If the successor is at the root, just return it. */
478 /* Otherwise, find the leftmost element of the right subtree. */
479 node
= sp
->root
->right
;
487 /* Call FN, passing it the DATA, for every node in SP, following an
488 in-order traversal. If FN every returns a non-zero value, the
489 iteration ceases immediately, and the value is returned.
490 Otherwise, this function returns 0. */
493 splay_tree_foreach (splay_tree sp
, splay_tree_foreach_fn fn
, void *data
)
495 return splay_tree_foreach_helper (sp
, sp
->root
, fn
, data
);
498 /* Splay-tree comparison function, treating the keys as ints. */
501 splay_tree_compare_ints (splay_tree_key k1
, splay_tree_key k2
)
503 if ((int) k1
< (int) k2
)
505 else if ((int) k1
> (int) k2
)
511 /* Splay-tree comparison function, treating the keys as pointers. */
514 splay_tree_compare_pointers (splay_tree_key k1
, splay_tree_key k2
)
516 if ((char*) k1
< (char*) k2
)
518 else if ((char*) k1
> (char*) k2
)