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