1 /* A splay-tree datatype.
2 Copyright (C) 1998, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
3 Contributed by Mark Mitchell (mark@markmitchell.com).
4 Adapted for libmudflap from libiberty.
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 In addition to the permissions in the GNU General Public License, the
14 Free Software Foundation gives you unlimited permission to link the
15 compiled version of this file into combinations with other programs,
16 and to distribute those combinations without any restriction coming
17 from the use of this file. (The General Public License restrictions
18 do apply in other respects; for example, they cover modification of
19 the file, and distribution when not linked into a combine
22 GNU CC is distributed in the hope that it will be useful, but
23 WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with GNU CC; see the file COPYING. If not, write to
29 the Free Software Foundation, 59 Temple Place - Suite 330,
30 Boston, MA 02111-1307, USA. */
32 /* For an easily readable description of splay-trees, see:
34 Lewis, Harry R. and Denenberg, Larry. Data Structures and Their
35 Algorithms. Harper-Collins, Inc. 1991. */
39 #include "splay-tree.h"
41 static void splay_tree_delete_helper PARAMS((splay_tree,
43 static void splay_tree_splay PARAMS((splay_tree,
45 static splay_tree_node splay_tree_splay_helper
51 static int splay_tree_foreach_helper PARAMS((splay_tree,
53 splay_tree_foreach_fn,
58 /* Inline comparison function specialized for libmudflap's key type. */
60 compare_uintptr_t (splay_tree_key k1, splay_tree_key k2)
62 if ((uintptr_t) k1 < (uintptr_t) k2)
64 else if ((uintptr_t) k1 > (uintptr_t) k2)
72 /* Deallocate NODE (a member of SP), and all its sub-trees. */
75 splay_tree_delete_helper (sp, node)
82 splay_tree_delete_helper (sp, node->left);
83 splay_tree_delete_helper (sp, node->right);
84 (*sp->deallocate) ((char*) node, sp->allocate_data);
87 /* Help splay SP around KEY. PARENT and GRANDPARENT are the parent
88 and grandparent, respectively, of NODE. */
90 static splay_tree_node
91 splay_tree_splay_helper (sp, key, node, parent, grandparent)
94 splay_tree_node *node;
95 splay_tree_node *parent;
96 splay_tree_node *grandparent;
98 splay_tree_node *next;
107 comparison = compare_uintptr_t (key, n->key);
110 /* We've found the target. */
112 else if (comparison < 0)
113 /* The target is to the left. */
116 /* The target is to the right. */
121 /* Continue down the tree. */
122 n = splay_tree_splay_helper (sp, key, next, node, parent);
124 /* The recursive call will change the place to which NODE
131 /* NODE is the root. We are done. */
134 /* First, handle the case where there is no grandparent (i.e.,
135 *PARENT is the root of the tree.) */
138 if (n == (*parent)->left)
152 /* Next handle the cases where both N and *PARENT are left children,
153 or where both are right children. */
154 if (n == (*parent)->left && *parent == (*grandparent)->left)
156 splay_tree_node p = *parent;
158 (*grandparent)->left = p->right;
159 p->right = *grandparent;
165 else if (n == (*parent)->right && *parent == (*grandparent)->right)
167 splay_tree_node p = *parent;
169 (*grandparent)->right = p->left;
170 p->left = *grandparent;
177 /* Finally, deal with the case where N is a left child, but *PARENT
178 is a right child, or vice versa. */
179 if (n == (*parent)->left)
181 (*parent)->left = n->right;
183 (*grandparent)->right = n->left;
184 n->left = *grandparent;
190 (*parent)->right = n->left;
192 (*grandparent)->left = n->right;
193 n->right = *grandparent;
199 /* Splay SP around KEY. */
202 splay_tree_splay (sp, key)
209 /* If we just splayed the tree with the same key, do nothing. */
210 if (sp->last_splayed_key_p &&
211 compare_uintptr_t (sp->last_splayed_key, key) == 0)
214 splay_tree_splay_helper (sp, key, &sp->root,
215 /*grandparent=*/0, /*parent=*/0);
217 /* Cache this splay key. */
218 sp->last_splayed_key = key;
219 sp->last_splayed_key_p = 1;
222 /* Call FN, passing it the DATA, for every node below NODE, all of
223 which are from SP, following an in-order traversal. If FN every
224 returns a non-zero value, the iteration ceases immediately, and the
225 value is returned. Otherwise, this function returns 0. */
228 splay_tree_foreach_helper (sp, node, fn, data)
230 splay_tree_node node;
231 splay_tree_foreach_fn fn;
239 val = splay_tree_foreach_helper (sp, node->left, fn, data);
243 val = (*fn)(node, data);
247 return splay_tree_foreach_helper (sp, node->right, fn, data);
251 /* An allocator and deallocator based on xmalloc. */
253 splay_tree_xmalloc_allocate (size, data)
255 void *data ATTRIBUTE_UNUSED;
257 return (void *) xmalloc (size);
261 splay_tree_xmalloc_deallocate (object, data)
263 void *data ATTRIBUTE_UNUSED;
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
277 splay_tree_allocate_fn allocate_fn = splay_tree_xmalloc_allocate;
278 splay_tree_deallocate_fn deallocate_fn = splay_tree_xmalloc_deallocate;
279 void *allocate_data = NULL;
280 splay_tree sp = (splay_tree) (*allocate_fn) (sizeof (struct splay_tree_s),
283 sp->allocate = allocate_fn;
284 sp->deallocate = deallocate_fn;
285 sp->allocate_data = allocate_data;
286 sp->last_splayed_key_p = 0;
294 splay_tree_delete (sp)
297 splay_tree_delete_helper (sp, sp->root);
298 (*sp->deallocate) ((char*) sp, sp->allocate_data);
301 /* Insert a new node (associating KEY with DATA) into SP. If a
302 previous node with the indicated KEY exists, its data is replaced
303 with the new value. Returns the new node. */
306 splay_tree_insert (sp, key, value)
309 splay_tree_value value;
313 splay_tree_splay (sp, key);
316 comparison = compare_uintptr_t (sp->root->key, key);
318 if (sp->root && comparison == 0)
320 /* If the root of the tree already has the indicated KEY, just
321 replace the value with VALUE. */
322 sp->root->value = value;
326 /* Create a new node, and insert it at the root. */
327 splay_tree_node node;
329 node = ((splay_tree_node)
330 (*sp->allocate) (sizeof (struct splay_tree_node_s),
336 node->left = node->right = 0;
337 else if (comparison < 0)
339 node->left = sp->root;
340 node->right = node->left->right;
341 node->left->right = 0;
345 node->right = sp->root;
346 node->left = node->right->left;
347 node->right->left = 0;
351 sp->last_splayed_key_p = 0;
357 /* Remove KEY from SP. It is not an error if it did not exist. */
360 splay_tree_remove (sp, key)
364 splay_tree_splay (sp, key);
365 sp->last_splayed_key_p = 0;
367 if (sp->root && compare_uintptr_t (sp->root->key, key) == 0)
369 splay_tree_node left, right;
371 left = sp->root->left;
372 right = sp->root->right;
374 /* Delete the root node itself. */
375 (*sp->deallocate) (sp->root, sp->allocate_data);
377 /* One of the children is now the root. Doesn't matter much
378 which, so long as we preserve the properties of the tree. */
383 /* If there was a right child as well, hang it off the
384 right-most leaf of the left child. */
397 /* Lookup KEY in SP, returning VALUE if present, and NULL
401 splay_tree_lookup (sp, key)
405 splay_tree_splay (sp, key);
407 if (sp->root && compare_uintptr_t (sp->root->key, key) == 0)
413 /* Return the node in SP with the greatest key. */
419 splay_tree_node n = sp->root;
430 /* Return the node in SP with the smallest key. */
436 splay_tree_node n = sp->root;
447 /* Return the immediate predecessor KEY, or NULL if there is no
448 predecessor. KEY need not be present in the tree. */
451 splay_tree_predecessor (sp, key)
456 splay_tree_node node;
458 /* If the tree is empty, there is certainly no predecessor. */
462 /* Splay the tree around KEY. That will leave either the KEY
463 itself, its predecessor, or its successor at the root. */
464 splay_tree_splay (sp, key);
465 comparison = compare_uintptr_t (sp->root->key, key);
467 /* If the predecessor is at the root, just return it. */
471 /* Otherwise, find the rightmost element of the left subtree. */
472 node = sp->root->left;
480 /* Return the immediate successor KEY, or NULL if there is no
481 successor. KEY need not be present in the tree. */
484 splay_tree_successor (sp, key)
489 splay_tree_node node;
491 /* If the tree is empty, there is certainly no successor. */
495 /* Splay the tree around KEY. That will leave either the KEY
496 itself, its predecessor, or its successor at the root. */
497 splay_tree_splay (sp, key);
498 comparison = compare_uintptr_t (sp->root->key, key);
500 /* If the successor is at the root, just return it. */
504 /* Otherwise, find the leftmost element of the right subtree. */
505 node = sp->root->right;
513 /* Call FN, passing it the DATA, for every node in SP, following an
514 in-order traversal. If FN every returns a non-zero value, the
515 iteration ceases immediately, and the value is returned.
516 Otherwise, this function returns 0. */
519 splay_tree_foreach (sp, fn, data)
521 splay_tree_foreach_fn fn;
524 return splay_tree_foreach_helper (sp, sp->root, fn, data);