1 /* A splay-tree datatype. 2 Copyright (C) 1998, 1999, 2000, 2001 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 #include <stdlib.h> 28 #include <stdio.h> 29 30 #include "magic_splay_tree.h" 31 32 #ifndef xmalloc 33 #define xmalloc malloc 34 #endif 35 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*); 44 45 /* Deallocate NODE (a member of SP), and all its sub-trees. */ 46 47 static void 48 splay_tree_delete_helper (splay_tree sp, splay_tree_node node) 49 { 50 splay_tree_node pending = 0; 51 splay_tree_node active = 0; 52 53 if (!node) 54 return; 55 56 #define KDEL(x) if (sp->delete_key) (*sp->delete_key)(x); 57 #define VDEL(x) if (sp->delete_value) (*sp->delete_value)(x); 58 59 KDEL (node->key); 60 VDEL (node->value); 61 62 /* We use the "key" field to hold the "next" pointer. */ 63 node->key = (splay_tree_key)pending; 64 pending = (splay_tree_node)node; 65 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. */ 69 70 while (pending) 71 { 72 active = pending; 73 pending = 0; 74 while (active) 75 { 76 splay_tree_node temp; 77 78 /* active points to a node which has its key and value 79 deallocated, we just need to process left and right. */ 80 81 if (active->left) 82 { 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); 87 } 88 if (active->right) 89 { 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); 94 } 95 96 temp = active; 97 active = (splay_tree_node)(temp->key); 98 (*sp->deallocate) ((char*) temp, sp->allocate_data); 99 } 100 } 101 #undef KDEL 102 #undef VDEL 103 } 104 105 /* Rotate the edge joining the left child N with its parent P. PP is the 106 grandparents pointer to P. */ 107 108 static inline void 109 rotate_left (splay_tree_node *pp, splay_tree_node p, splay_tree_node n) 110 { 111 splay_tree_node tmp; 112 tmp = n->right; 113 n->right = p; 114 p->left = tmp; 115 *pp = n; 116 } 117 118 /* Rotate the edge joining the right child N with its parent P. PP is the 119 grandparents pointer to P. */ 120 121 static inline void 122 rotate_right (splay_tree_node *pp, splay_tree_node p, splay_tree_node n) 123 { 124 splay_tree_node tmp; 125 tmp = n->left; 126 n->left = p; 127 p->right = tmp; 128 *pp = n; 129 } 130 131 /* Bottom up splay of key. */ 132 133 static void 134 splay_tree_splay (splay_tree sp, splay_tree_key key) 135 { 136 if (sp->root == 0) 137 return; 138 139 do { 140 int cmp1, cmp2; 141 splay_tree_node n, c; 142 143 n = sp->root; 144 cmp1 = (*sp->comp) (key, n->key); 145 146 /* Found. */ 147 if (cmp1 == 0) 148 return; 149 150 /* Left or right? If no child, then we're done. */ 151 if (cmp1 < 0) 152 c = n->left; 153 else 154 c = n->right; 155 if (!c) 156 return; 157 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); 161 if (cmp2 == 0 162 || (cmp2 < 0 && !c->left) 163 || (cmp2 > 0 && !c->right)) 164 { 165 if (cmp1 < 0) 166 rotate_left (&sp->root, n, c); 167 else 168 rotate_right (&sp->root, n, c); 169 return; 170 } 171 172 /* Now we have the four cases of double-rotation. */ 173 if (cmp1 < 0 && cmp2 < 0) 174 { 175 rotate_left (&n->left, c, c->left); 176 rotate_left (&sp->root, n, n->left); 177 } 178 else if (cmp1 > 0 && cmp2 > 0) 179 { 180 rotate_right (&n->right, c, c->right); 181 rotate_right (&sp->root, n, n->right); 182 } 183 else if (cmp1 < 0 && cmp2 > 0) 184 { 185 rotate_right (&n->left, c, c->right); 186 rotate_left (&sp->root, n, n->left); 187 } 188 else if (cmp1 > 0 && cmp2 < 0) 189 { 190 rotate_left (&n->right, c, c->left); 191 rotate_right (&sp->root, n, n->right); 192 } 193 } while (1); 194 } 195 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. */ 200 201 static int 202 splay_tree_foreach_helper (splay_tree sp, splay_tree_node node, 203 splay_tree_foreach_fn fn, void *data) 204 { 205 int val; 206 207 if (!node) 208 return 0; 209 210 val = splay_tree_foreach_helper (sp, node->left, fn, data); 211 if (val) 212 return val; 213 214 val = (*fn)(node, data); 215 if (val) 216 return val; 217 218 return splay_tree_foreach_helper (sp, node->right, fn, data); 219 } 220 221 222 /* An allocator and deallocator based on xmalloc. */ 223 static void * 224 splay_tree_xmalloc_allocate (int size, void *data ATTRIBUTE_UNUSED) 225 { 226 return (void *) xmalloc (size); 227 } 228 229 static void 230 splay_tree_xmalloc_deallocate (void *object, void *data ATTRIBUTE_UNUSED) 231 { 232 free (object); 233 } 234 235 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 239 nodes added. */ 240 241 splay_tree 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) 245 { 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)); 249 } 250 251 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 254 values. */ 255 256 splay_tree 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, 262 void *allocate_data) 263 { 264 splay_tree sp = (splay_tree) (*allocate_fn) (sizeof (struct splay_tree_s), 265 allocate_data); 266 sp->root = 0; 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; 273 274 return sp; 275 } 276 277 /* Deallocate SP. */ 278 279 void 280 splay_tree_delete (splay_tree sp) 281 { 282 splay_tree_delete_helper (sp, sp->root); 283 (*sp->deallocate) ((char*) sp, sp->allocate_data); 284 } 285 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. */ 289 290 splay_tree_node 291 splay_tree_insert (splay_tree sp, splay_tree_key key, splay_tree_value value) 292 { 293 int comparison = 0; 294 295 splay_tree_splay (sp, key); 296 297 if (sp->root) 298 comparison = (*sp->comp)(sp->root->key, key); 299 300 if (sp->root && comparison == 0) 301 { 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; 307 } 308 else 309 { 310 /* Create a new node, and insert it at the root. */ 311 splay_tree_node node; 312 313 node = ((splay_tree_node) 314 (*sp->allocate) (sizeof (struct splay_tree_node_s), 315 sp->allocate_data)); 316 node->key = key; 317 node->value = value; 318 319 if (!sp->root) 320 node->left = node->right = 0; 321 else if (comparison < 0) 322 { 323 node->left = sp->root; 324 node->right = node->left->right; 325 node->left->right = 0; 326 } 327 else 328 { 329 node->right = sp->root; 330 node->left = node->right->left; 331 node->right->left = 0; 332 } 333 334 sp->root = node; 335 } 336 337 return sp->root; 338 } 339 340 /* Remove KEY from SP. It is not an error if it did not exist. */ 341 342 void 343 splay_tree_remove (splay_tree sp, splay_tree_key key) 344 { 345 splay_tree_splay (sp, key); 346 347 if (sp->root && (*sp->comp) (sp->root->key, key) == 0) 348 { 349 splay_tree_node left, right; 350 351 left = sp->root->left; 352 right = sp->root->right; 353 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); 358 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. */ 361 if (left) 362 { 363 sp->root = left; 364 365 /* If there was a right child as well, hang it off the 366 right-most leaf of the left child. */ 367 if (right) 368 { 369 while (left->right) 370 left = left->right; 371 left->right = right; 372 } 373 } 374 else 375 sp->root = right; 376 } 377 } 378 379 /* Lookup KEY in SP, returning VALUE if present, and NULL 380 otherwise. */ 381 382 splay_tree_node 383 splay_tree_lookup (splay_tree sp, splay_tree_key key) 384 { 385 splay_tree_splay (sp, key); 386 387 if (sp->root && (*sp->comp)(sp->root->key, key) == 0) 388 return sp->root; 389 else 390 return 0; 391 } 392 393 /* Return the node in SP with the greatest key. */ 394 395 splay_tree_node 396 splay_tree_max (splay_tree sp) 397 { 398 splay_tree_node n = sp->root; 399 400 if (!n) 401 return NULL; 402 403 while (n->right) 404 n = n->right; 405 406 return n; 407 } 408 409 /* Return the node in SP with the smallest key. */ 410 411 splay_tree_node 412 splay_tree_min (splay_tree sp) 413 { 414 splay_tree_node n = sp->root; 415 416 if (!n) 417 return NULL; 418 419 while (n->left) 420 n = n->left; 421 422 return n; 423 } 424 425 /* Return the immediate predecessor KEY, or NULL if there is no 426 predecessor. KEY need not be present in the tree. */ 427 428 splay_tree_node 429 splay_tree_predecessor (splay_tree sp, splay_tree_key key) 430 { 431 int comparison; 432 splay_tree_node node; 433 434 /* If the tree is empty, there is certainly no predecessor. */ 435 if (!sp->root) 436 return NULL; 437 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); 442 443 /* If the predecessor is at the root, just return it. */ 444 if (comparison < 0) 445 return sp->root; 446 447 /* Otherwise, find the rightmost element of the left subtree. */ 448 node = sp->root->left; 449 if (node) 450 while (node->right) 451 node = node->right; 452 453 return node; 454 } 455 456 /* Return the immediate successor KEY, or NULL if there is no 457 successor. KEY need not be present in the tree. */ 458 459 splay_tree_node 460 splay_tree_successor (splay_tree sp, splay_tree_key key) 461 { 462 int comparison; 463 splay_tree_node node; 464 465 /* If the tree is empty, there is certainly no successor. */ 466 if (!sp->root) 467 return NULL; 468 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); 473 474 /* If the successor is at the root, just return it. */ 475 if (comparison > 0) 476 return sp->root; 477 478 /* Otherwise, find the leftmost element of the right subtree. */ 479 node = sp->root->right; 480 if (node) 481 while (node->left) 482 node = node->left; 483 484 return node; 485 } 486 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. */ 491 492 int 493 splay_tree_foreach (splay_tree sp, splay_tree_foreach_fn fn, void *data) 494 { 495 return splay_tree_foreach_helper (sp, sp->root, fn, data); 496 } 497 498 /* Splay-tree comparison function, treating the keys as ints. */ 499 500 int 501 splay_tree_compare_ints (splay_tree_key k1, splay_tree_key k2) 502 { 503 if ((int) k1 < (int) k2) 504 return -1; 505 else if ((int) k1 > (int) k2) 506 return 1; 507 else 508 return 0; 509 } 510 511 /* Splay-tree comparison function, treating the keys as pointers. */ 512 513 int 514 splay_tree_compare_pointers (splay_tree_key k1, splay_tree_key k2) 515 { 516 if ((char*) k1 < (char*) k2) 517 return -1; 518 else if ((char*) k1 > (char*) k2) 519 return 1; 520 else 521 return 0; 522 } 523 524