198b9484cSchristos /* A splay-tree datatype. 2*7e120ff0Schristos Copyright (C) 1998-2024 Free Software Foundation, Inc. 398b9484cSchristos Contributed by Mark Mitchell (mark@markmitchell.com). 498b9484cSchristos 598b9484cSchristos This file is part of GNU CC. 698b9484cSchristos 798b9484cSchristos GNU CC is free software; you can redistribute it and/or modify it 898b9484cSchristos under the terms of the GNU General Public License as published by 998b9484cSchristos the Free Software Foundation; either version 2, or (at your option) 1098b9484cSchristos any later version. 1198b9484cSchristos 1298b9484cSchristos GNU CC is distributed in the hope that it will be useful, but 1398b9484cSchristos WITHOUT ANY WARRANTY; without even the implied warranty of 1498b9484cSchristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1598b9484cSchristos General Public License for more details. 1698b9484cSchristos 1798b9484cSchristos You should have received a copy of the GNU General Public License 1898b9484cSchristos along with GNU CC; see the file COPYING. If not, write to 1998b9484cSchristos the Free Software Foundation, 51 Franklin Street - Fifth Floor, 2098b9484cSchristos Boston, MA 02110-1301, USA. */ 2198b9484cSchristos 2298b9484cSchristos /* For an easily readable description of splay-trees, see: 2398b9484cSchristos 2498b9484cSchristos Lewis, Harry R. and Denenberg, Larry. Data Structures and Their 2598b9484cSchristos Algorithms. Harper-Collins, Inc. 1991. */ 2698b9484cSchristos 2798b9484cSchristos #ifdef HAVE_CONFIG_H 2898b9484cSchristos #include "config.h" 2998b9484cSchristos #endif 3098b9484cSchristos 3198b9484cSchristos #ifdef HAVE_STDLIB_H 3298b9484cSchristos #include <stdlib.h> 3398b9484cSchristos #endif 344559860eSchristos #ifdef HAVE_STRING_H 354559860eSchristos #include <string.h> 364559860eSchristos #endif 3798b9484cSchristos 3898b9484cSchristos #include <stdio.h> 3998b9484cSchristos 4098b9484cSchristos #include "libiberty.h" 4198b9484cSchristos #include "splay-tree.h" 4298b9484cSchristos 4398b9484cSchristos static void splay_tree_delete_helper (splay_tree, splay_tree_node); 4498b9484cSchristos static inline void rotate_left (splay_tree_node *, 4598b9484cSchristos splay_tree_node, splay_tree_node); 4698b9484cSchristos static inline void rotate_right (splay_tree_node *, 4798b9484cSchristos splay_tree_node, splay_tree_node); 4898b9484cSchristos static void splay_tree_splay (splay_tree, splay_tree_key); 4998b9484cSchristos static int splay_tree_foreach_helper (splay_tree_node, 5098b9484cSchristos splay_tree_foreach_fn, void*); 5198b9484cSchristos 5298b9484cSchristos /* Deallocate NODE (a member of SP), and all its sub-trees. */ 5398b9484cSchristos 5498b9484cSchristos static void 5598b9484cSchristos splay_tree_delete_helper (splay_tree sp, splay_tree_node node) 5698b9484cSchristos { 5798b9484cSchristos splay_tree_node pending = 0; 5898b9484cSchristos splay_tree_node active = 0; 5998b9484cSchristos 6098b9484cSchristos if (!node) 6198b9484cSchristos return; 6298b9484cSchristos 6398b9484cSchristos #define KDEL(x) if (sp->delete_key) (*sp->delete_key)(x); 6498b9484cSchristos #define VDEL(x) if (sp->delete_value) (*sp->delete_value)(x); 6598b9484cSchristos 6698b9484cSchristos KDEL (node->key); 6798b9484cSchristos VDEL (node->value); 6898b9484cSchristos 6998b9484cSchristos /* We use the "key" field to hold the "next" pointer. */ 7098b9484cSchristos node->key = (splay_tree_key)pending; 7198b9484cSchristos pending = (splay_tree_node)node; 7298b9484cSchristos 7398b9484cSchristos /* Now, keep processing the pending list until there aren't any 7498b9484cSchristos more. This is a little more complicated than just recursing, but 7598b9484cSchristos it doesn't toast the stack for large trees. */ 7698b9484cSchristos 7798b9484cSchristos while (pending) 7898b9484cSchristos { 7998b9484cSchristos active = pending; 8098b9484cSchristos pending = 0; 8198b9484cSchristos while (active) 8298b9484cSchristos { 8398b9484cSchristos splay_tree_node temp; 8498b9484cSchristos 8598b9484cSchristos /* active points to a node which has its key and value 8698b9484cSchristos deallocated, we just need to process left and right. */ 8798b9484cSchristos 8898b9484cSchristos if (active->left) 8998b9484cSchristos { 9098b9484cSchristos KDEL (active->left->key); 9198b9484cSchristos VDEL (active->left->value); 9298b9484cSchristos active->left->key = (splay_tree_key)pending; 9398b9484cSchristos pending = (splay_tree_node)(active->left); 9498b9484cSchristos } 9598b9484cSchristos if (active->right) 9698b9484cSchristos { 9798b9484cSchristos KDEL (active->right->key); 9898b9484cSchristos VDEL (active->right->value); 9998b9484cSchristos active->right->key = (splay_tree_key)pending; 10098b9484cSchristos pending = (splay_tree_node)(active->right); 10198b9484cSchristos } 10298b9484cSchristos 10398b9484cSchristos temp = active; 10498b9484cSchristos active = (splay_tree_node)(temp->key); 10598b9484cSchristos (*sp->deallocate) ((char*) temp, sp->allocate_data); 10698b9484cSchristos } 10798b9484cSchristos } 10898b9484cSchristos #undef KDEL 10998b9484cSchristos #undef VDEL 11098b9484cSchristos } 11198b9484cSchristos 11298b9484cSchristos /* Rotate the edge joining the left child N with its parent P. PP is the 11398b9484cSchristos grandparents' pointer to P. */ 11498b9484cSchristos 11598b9484cSchristos static inline void 11698b9484cSchristos rotate_left (splay_tree_node *pp, splay_tree_node p, splay_tree_node n) 11798b9484cSchristos { 11898b9484cSchristos splay_tree_node tmp; 11998b9484cSchristos tmp = n->right; 12098b9484cSchristos n->right = p; 12198b9484cSchristos p->left = tmp; 12298b9484cSchristos *pp = n; 12398b9484cSchristos } 12498b9484cSchristos 12598b9484cSchristos /* Rotate the edge joining the right child N with its parent P. PP is the 12698b9484cSchristos grandparents' pointer to P. */ 12798b9484cSchristos 12898b9484cSchristos static inline void 12998b9484cSchristos rotate_right (splay_tree_node *pp, splay_tree_node p, splay_tree_node n) 13098b9484cSchristos { 13198b9484cSchristos splay_tree_node tmp; 13298b9484cSchristos tmp = n->left; 13398b9484cSchristos n->left = p; 13498b9484cSchristos p->right = tmp; 13598b9484cSchristos *pp = n; 13698b9484cSchristos } 13798b9484cSchristos 13898b9484cSchristos /* Bottom up splay of key. */ 13998b9484cSchristos 14098b9484cSchristos static void 14198b9484cSchristos splay_tree_splay (splay_tree sp, splay_tree_key key) 14298b9484cSchristos { 14398b9484cSchristos if (sp->root == 0) 14498b9484cSchristos return; 14598b9484cSchristos 14698b9484cSchristos do { 14798b9484cSchristos int cmp1, cmp2; 14898b9484cSchristos splay_tree_node n, c; 14998b9484cSchristos 15098b9484cSchristos n = sp->root; 15198b9484cSchristos cmp1 = (*sp->comp) (key, n->key); 15298b9484cSchristos 15398b9484cSchristos /* Found. */ 15498b9484cSchristos if (cmp1 == 0) 15598b9484cSchristos return; 15698b9484cSchristos 15798b9484cSchristos /* Left or right? If no child, then we're done. */ 15898b9484cSchristos if (cmp1 < 0) 15998b9484cSchristos c = n->left; 16098b9484cSchristos else 16198b9484cSchristos c = n->right; 16298b9484cSchristos if (!c) 16398b9484cSchristos return; 16498b9484cSchristos 16598b9484cSchristos /* Next one left or right? If found or no child, we're done 16698b9484cSchristos after one rotation. */ 16798b9484cSchristos cmp2 = (*sp->comp) (key, c->key); 16898b9484cSchristos if (cmp2 == 0 16998b9484cSchristos || (cmp2 < 0 && !c->left) 17098b9484cSchristos || (cmp2 > 0 && !c->right)) 17198b9484cSchristos { 17298b9484cSchristos if (cmp1 < 0) 17398b9484cSchristos rotate_left (&sp->root, n, c); 17498b9484cSchristos else 17598b9484cSchristos rotate_right (&sp->root, n, c); 17698b9484cSchristos return; 17798b9484cSchristos } 17898b9484cSchristos 17998b9484cSchristos /* Now we have the four cases of double-rotation. */ 18098b9484cSchristos if (cmp1 < 0 && cmp2 < 0) 18198b9484cSchristos { 18298b9484cSchristos rotate_left (&n->left, c, c->left); 18398b9484cSchristos rotate_left (&sp->root, n, n->left); 18498b9484cSchristos } 18598b9484cSchristos else if (cmp1 > 0 && cmp2 > 0) 18698b9484cSchristos { 18798b9484cSchristos rotate_right (&n->right, c, c->right); 18898b9484cSchristos rotate_right (&sp->root, n, n->right); 18998b9484cSchristos } 19098b9484cSchristos else if (cmp1 < 0 && cmp2 > 0) 19198b9484cSchristos { 19298b9484cSchristos rotate_right (&n->left, c, c->right); 19398b9484cSchristos rotate_left (&sp->root, n, n->left); 19498b9484cSchristos } 19598b9484cSchristos else if (cmp1 > 0 && cmp2 < 0) 19698b9484cSchristos { 19798b9484cSchristos rotate_left (&n->right, c, c->left); 19898b9484cSchristos rotate_right (&sp->root, n, n->right); 19998b9484cSchristos } 20098b9484cSchristos } while (1); 20198b9484cSchristos } 20298b9484cSchristos 20398b9484cSchristos /* Call FN, passing it the DATA, for every node below NODE, all of 20498b9484cSchristos which are from SP, following an in-order traversal. If FN every 20598b9484cSchristos returns a non-zero value, the iteration ceases immediately, and the 20698b9484cSchristos value is returned. Otherwise, this function returns 0. */ 20798b9484cSchristos 20898b9484cSchristos static int 20998b9484cSchristos splay_tree_foreach_helper (splay_tree_node node, 21098b9484cSchristos splay_tree_foreach_fn fn, void *data) 21198b9484cSchristos { 21298b9484cSchristos int val; 21398b9484cSchristos splay_tree_node *stack; 21498b9484cSchristos int stack_ptr, stack_size; 21598b9484cSchristos 21698b9484cSchristos /* A non-recursive implementation is used to avoid filling the stack 21798b9484cSchristos for large trees. Splay trees are worst case O(n) in the depth of 21898b9484cSchristos the tree. */ 21998b9484cSchristos 22098b9484cSchristos #define INITIAL_STACK_SIZE 100 22198b9484cSchristos stack_size = INITIAL_STACK_SIZE; 22298b9484cSchristos stack_ptr = 0; 22398b9484cSchristos stack = XNEWVEC (splay_tree_node, stack_size); 22498b9484cSchristos val = 0; 22598b9484cSchristos 22698b9484cSchristos for (;;) 22798b9484cSchristos { 22898b9484cSchristos while (node != NULL) 22998b9484cSchristos { 23098b9484cSchristos if (stack_ptr == stack_size) 23198b9484cSchristos { 23298b9484cSchristos stack_size *= 2; 23398b9484cSchristos stack = XRESIZEVEC (splay_tree_node, stack, stack_size); 23498b9484cSchristos } 23598b9484cSchristos stack[stack_ptr++] = node; 23698b9484cSchristos node = node->left; 23798b9484cSchristos } 23898b9484cSchristos 23998b9484cSchristos if (stack_ptr == 0) 24098b9484cSchristos break; 24198b9484cSchristos 24298b9484cSchristos node = stack[--stack_ptr]; 24398b9484cSchristos 24498b9484cSchristos val = (*fn) (node, data); 24598b9484cSchristos if (val) 24698b9484cSchristos break; 24798b9484cSchristos 24898b9484cSchristos node = node->right; 24998b9484cSchristos } 25098b9484cSchristos 25198b9484cSchristos XDELETEVEC (stack); 25298b9484cSchristos return val; 25398b9484cSchristos } 25498b9484cSchristos 25598b9484cSchristos /* An allocator and deallocator based on xmalloc. */ 25698b9484cSchristos static void * 25798b9484cSchristos splay_tree_xmalloc_allocate (int size, void *data ATTRIBUTE_UNUSED) 25898b9484cSchristos { 25998b9484cSchristos return (void *) xmalloc (size); 26098b9484cSchristos } 26198b9484cSchristos 26298b9484cSchristos static void 26398b9484cSchristos splay_tree_xmalloc_deallocate (void *object, void *data ATTRIBUTE_UNUSED) 26498b9484cSchristos { 26598b9484cSchristos free (object); 26698b9484cSchristos } 26798b9484cSchristos 26898b9484cSchristos 26998b9484cSchristos /* Allocate a new splay tree, using COMPARE_FN to compare nodes, 27098b9484cSchristos DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate 27198b9484cSchristos values. Use xmalloc to allocate the splay tree structure, and any 27298b9484cSchristos nodes added. */ 27398b9484cSchristos 27498b9484cSchristos splay_tree 27598b9484cSchristos splay_tree_new (splay_tree_compare_fn compare_fn, 27698b9484cSchristos splay_tree_delete_key_fn delete_key_fn, 27798b9484cSchristos splay_tree_delete_value_fn delete_value_fn) 27898b9484cSchristos { 27998b9484cSchristos return (splay_tree_new_with_allocator 28098b9484cSchristos (compare_fn, delete_key_fn, delete_value_fn, 28198b9484cSchristos splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate, 0)); 28298b9484cSchristos } 28398b9484cSchristos 28498b9484cSchristos 28598b9484cSchristos /* Allocate a new splay tree, using COMPARE_FN to compare nodes, 28698b9484cSchristos DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate 28798b9484cSchristos values. */ 28898b9484cSchristos 28998b9484cSchristos splay_tree 29098b9484cSchristos splay_tree_new_with_allocator (splay_tree_compare_fn compare_fn, 29198b9484cSchristos splay_tree_delete_key_fn delete_key_fn, 29298b9484cSchristos splay_tree_delete_value_fn delete_value_fn, 29398b9484cSchristos splay_tree_allocate_fn allocate_fn, 29498b9484cSchristos splay_tree_deallocate_fn deallocate_fn, 29598b9484cSchristos void *allocate_data) 29698b9484cSchristos { 29798b9484cSchristos return 29898b9484cSchristos splay_tree_new_typed_alloc (compare_fn, delete_key_fn, delete_value_fn, 29998b9484cSchristos allocate_fn, allocate_fn, deallocate_fn, 30098b9484cSchristos allocate_data); 30198b9484cSchristos } 30298b9484cSchristos 30398b9484cSchristos /* 30498b9484cSchristos 30598b9484cSchristos @deftypefn Supplemental splay_tree splay_tree_new_with_typed_alloc @ 30698b9484cSchristos (splay_tree_compare_fn @var{compare_fn}, @ 30798b9484cSchristos splay_tree_delete_key_fn @var{delete_key_fn}, @ 30898b9484cSchristos splay_tree_delete_value_fn @var{delete_value_fn}, @ 30998b9484cSchristos splay_tree_allocate_fn @var{tree_allocate_fn}, @ 31098b9484cSchristos splay_tree_allocate_fn @var{node_allocate_fn}, @ 31198b9484cSchristos splay_tree_deallocate_fn @var{deallocate_fn}, @ 31298b9484cSchristos void * @var{allocate_data}) 31398b9484cSchristos 31498b9484cSchristos This function creates a splay tree that uses two different allocators 31598b9484cSchristos @var{tree_allocate_fn} and @var{node_allocate_fn} to use for allocating the 31698b9484cSchristos tree itself and its nodes respectively. This is useful when variables of 31798b9484cSchristos different types need to be allocated with different allocators. 31898b9484cSchristos 31998b9484cSchristos The splay tree will use @var{compare_fn} to compare nodes, 32098b9484cSchristos @var{delete_key_fn} to deallocate keys, and @var{delete_value_fn} to 3214559860eSchristos deallocate values. Keys and values will be deallocated when the 3224559860eSchristos tree is deleted using splay_tree_delete or when a node is removed 3234559860eSchristos using splay_tree_remove. splay_tree_insert will release the previously 3244559860eSchristos inserted key and value using @var{delete_key_fn} and @var{delete_value_fn} 3254559860eSchristos if the inserted key is already found in the tree. 32698b9484cSchristos 32798b9484cSchristos @end deftypefn 32898b9484cSchristos 32998b9484cSchristos */ 33098b9484cSchristos 33198b9484cSchristos splay_tree 33298b9484cSchristos splay_tree_new_typed_alloc (splay_tree_compare_fn compare_fn, 33398b9484cSchristos splay_tree_delete_key_fn delete_key_fn, 33498b9484cSchristos splay_tree_delete_value_fn delete_value_fn, 33598b9484cSchristos splay_tree_allocate_fn tree_allocate_fn, 33698b9484cSchristos splay_tree_allocate_fn node_allocate_fn, 33798b9484cSchristos splay_tree_deallocate_fn deallocate_fn, 33898b9484cSchristos void * allocate_data) 33998b9484cSchristos { 34098b9484cSchristos splay_tree sp = (splay_tree) (*tree_allocate_fn) 34198b9484cSchristos (sizeof (struct splay_tree_s), allocate_data); 34298b9484cSchristos 34398b9484cSchristos sp->root = 0; 34498b9484cSchristos sp->comp = compare_fn; 34598b9484cSchristos sp->delete_key = delete_key_fn; 34698b9484cSchristos sp->delete_value = delete_value_fn; 34798b9484cSchristos sp->allocate = node_allocate_fn; 34898b9484cSchristos sp->deallocate = deallocate_fn; 34998b9484cSchristos sp->allocate_data = allocate_data; 35098b9484cSchristos 35198b9484cSchristos return sp; 35298b9484cSchristos } 35398b9484cSchristos 35498b9484cSchristos /* Deallocate SP. */ 35598b9484cSchristos 35698b9484cSchristos void 35798b9484cSchristos splay_tree_delete (splay_tree sp) 35898b9484cSchristos { 35998b9484cSchristos splay_tree_delete_helper (sp, sp->root); 36098b9484cSchristos (*sp->deallocate) ((char*) sp, sp->allocate_data); 36198b9484cSchristos } 36298b9484cSchristos 36398b9484cSchristos /* Insert a new node (associating KEY with DATA) into SP. If a 36498b9484cSchristos previous node with the indicated KEY exists, its data is replaced 36598b9484cSchristos with the new value. Returns the new node. */ 36698b9484cSchristos 36798b9484cSchristos splay_tree_node 36898b9484cSchristos splay_tree_insert (splay_tree sp, splay_tree_key key, splay_tree_value value) 36998b9484cSchristos { 37098b9484cSchristos int comparison = 0; 37198b9484cSchristos 37298b9484cSchristos splay_tree_splay (sp, key); 37398b9484cSchristos 37498b9484cSchristos if (sp->root) 37598b9484cSchristos comparison = (*sp->comp)(sp->root->key, key); 37698b9484cSchristos 37798b9484cSchristos if (sp->root && comparison == 0) 37898b9484cSchristos { 3794559860eSchristos /* If the root of the tree already has the indicated KEY, delete 3804559860eSchristos the old key and old value, and replace them with KEY and VALUE. */ 3814559860eSchristos if (sp->delete_key) 3824559860eSchristos (*sp->delete_key) (sp->root->key); 38398b9484cSchristos if (sp->delete_value) 38498b9484cSchristos (*sp->delete_value)(sp->root->value); 3854559860eSchristos sp->root->key = key; 38698b9484cSchristos sp->root->value = value; 38798b9484cSchristos } 38898b9484cSchristos else 38998b9484cSchristos { 39098b9484cSchristos /* Create a new node, and insert it at the root. */ 39198b9484cSchristos splay_tree_node node; 39298b9484cSchristos 39398b9484cSchristos node = ((splay_tree_node) 39498b9484cSchristos (*sp->allocate) (sizeof (struct splay_tree_node_s), 39598b9484cSchristos sp->allocate_data)); 39698b9484cSchristos node->key = key; 39798b9484cSchristos node->value = value; 39898b9484cSchristos 39998b9484cSchristos if (!sp->root) 40098b9484cSchristos node->left = node->right = 0; 40198b9484cSchristos else if (comparison < 0) 40298b9484cSchristos { 40398b9484cSchristos node->left = sp->root; 40498b9484cSchristos node->right = node->left->right; 40598b9484cSchristos node->left->right = 0; 40698b9484cSchristos } 40798b9484cSchristos else 40898b9484cSchristos { 40998b9484cSchristos node->right = sp->root; 41098b9484cSchristos node->left = node->right->left; 41198b9484cSchristos node->right->left = 0; 41298b9484cSchristos } 41398b9484cSchristos 41498b9484cSchristos sp->root = node; 41598b9484cSchristos } 41698b9484cSchristos 41798b9484cSchristos return sp->root; 41898b9484cSchristos } 41998b9484cSchristos 42098b9484cSchristos /* Remove KEY from SP. It is not an error if it did not exist. */ 42198b9484cSchristos 42298b9484cSchristos void 42398b9484cSchristos splay_tree_remove (splay_tree sp, splay_tree_key key) 42498b9484cSchristos { 42598b9484cSchristos splay_tree_splay (sp, key); 42698b9484cSchristos 42798b9484cSchristos if (sp->root && (*sp->comp) (sp->root->key, key) == 0) 42898b9484cSchristos { 42998b9484cSchristos splay_tree_node left, right; 43098b9484cSchristos 43198b9484cSchristos left = sp->root->left; 43298b9484cSchristos right = sp->root->right; 43398b9484cSchristos 43498b9484cSchristos /* Delete the root node itself. */ 4354559860eSchristos if (sp->delete_key) 4364559860eSchristos (*sp->delete_key) (sp->root->key); 43798b9484cSchristos if (sp->delete_value) 43898b9484cSchristos (*sp->delete_value) (sp->root->value); 43998b9484cSchristos (*sp->deallocate) (sp->root, sp->allocate_data); 44098b9484cSchristos 44198b9484cSchristos /* One of the children is now the root. Doesn't matter much 44298b9484cSchristos which, so long as we preserve the properties of the tree. */ 44398b9484cSchristos if (left) 44498b9484cSchristos { 44598b9484cSchristos sp->root = left; 44698b9484cSchristos 44798b9484cSchristos /* If there was a right child as well, hang it off the 44898b9484cSchristos right-most leaf of the left child. */ 44998b9484cSchristos if (right) 45098b9484cSchristos { 45198b9484cSchristos while (left->right) 45298b9484cSchristos left = left->right; 45398b9484cSchristos left->right = right; 45498b9484cSchristos } 45598b9484cSchristos } 45698b9484cSchristos else 45798b9484cSchristos sp->root = right; 45898b9484cSchristos } 45998b9484cSchristos } 46098b9484cSchristos 46198b9484cSchristos /* Lookup KEY in SP, returning VALUE if present, and NULL 46298b9484cSchristos otherwise. */ 46398b9484cSchristos 46498b9484cSchristos splay_tree_node 46598b9484cSchristos splay_tree_lookup (splay_tree sp, splay_tree_key key) 46698b9484cSchristos { 46798b9484cSchristos splay_tree_splay (sp, key); 46898b9484cSchristos 46998b9484cSchristos if (sp->root && (*sp->comp)(sp->root->key, key) == 0) 47098b9484cSchristos return sp->root; 47198b9484cSchristos else 47298b9484cSchristos return 0; 47398b9484cSchristos } 47498b9484cSchristos 47598b9484cSchristos /* Return the node in SP with the greatest key. */ 47698b9484cSchristos 47798b9484cSchristos splay_tree_node 47898b9484cSchristos splay_tree_max (splay_tree sp) 47998b9484cSchristos { 48098b9484cSchristos splay_tree_node n = sp->root; 48198b9484cSchristos 48298b9484cSchristos if (!n) 48398b9484cSchristos return NULL; 48498b9484cSchristos 48598b9484cSchristos while (n->right) 48698b9484cSchristos n = n->right; 48798b9484cSchristos 48898b9484cSchristos return n; 48998b9484cSchristos } 49098b9484cSchristos 49198b9484cSchristos /* Return the node in SP with the smallest key. */ 49298b9484cSchristos 49398b9484cSchristos splay_tree_node 49498b9484cSchristos splay_tree_min (splay_tree sp) 49598b9484cSchristos { 49698b9484cSchristos splay_tree_node n = sp->root; 49798b9484cSchristos 49898b9484cSchristos if (!n) 49998b9484cSchristos return NULL; 50098b9484cSchristos 50198b9484cSchristos while (n->left) 50298b9484cSchristos n = n->left; 50398b9484cSchristos 50498b9484cSchristos return n; 50598b9484cSchristos } 50698b9484cSchristos 50798b9484cSchristos /* Return the immediate predecessor KEY, or NULL if there is no 50898b9484cSchristos predecessor. KEY need not be present in the tree. */ 50998b9484cSchristos 51098b9484cSchristos splay_tree_node 51198b9484cSchristos splay_tree_predecessor (splay_tree sp, splay_tree_key key) 51298b9484cSchristos { 51398b9484cSchristos int comparison; 51498b9484cSchristos splay_tree_node node; 51598b9484cSchristos 51698b9484cSchristos /* If the tree is empty, there is certainly no predecessor. */ 51798b9484cSchristos if (!sp->root) 51898b9484cSchristos return NULL; 51998b9484cSchristos 52098b9484cSchristos /* Splay the tree around KEY. That will leave either the KEY 52198b9484cSchristos itself, its predecessor, or its successor at the root. */ 52298b9484cSchristos splay_tree_splay (sp, key); 52398b9484cSchristos comparison = (*sp->comp)(sp->root->key, key); 52498b9484cSchristos 52598b9484cSchristos /* If the predecessor is at the root, just return it. */ 52698b9484cSchristos if (comparison < 0) 52798b9484cSchristos return sp->root; 52898b9484cSchristos 52998b9484cSchristos /* Otherwise, find the rightmost element of the left subtree. */ 53098b9484cSchristos node = sp->root->left; 53198b9484cSchristos if (node) 53298b9484cSchristos while (node->right) 53398b9484cSchristos node = node->right; 53498b9484cSchristos 53598b9484cSchristos return node; 53698b9484cSchristos } 53798b9484cSchristos 53898b9484cSchristos /* Return the immediate successor KEY, or NULL if there is no 53998b9484cSchristos successor. KEY need not be present in the tree. */ 54098b9484cSchristos 54198b9484cSchristos splay_tree_node 54298b9484cSchristos splay_tree_successor (splay_tree sp, splay_tree_key key) 54398b9484cSchristos { 54498b9484cSchristos int comparison; 54598b9484cSchristos splay_tree_node node; 54698b9484cSchristos 54798b9484cSchristos /* If the tree is empty, there is certainly no successor. */ 54898b9484cSchristos if (!sp->root) 54998b9484cSchristos return NULL; 55098b9484cSchristos 55198b9484cSchristos /* Splay the tree around KEY. That will leave either the KEY 55298b9484cSchristos itself, its predecessor, or its successor at the root. */ 55398b9484cSchristos splay_tree_splay (sp, key); 55498b9484cSchristos comparison = (*sp->comp)(sp->root->key, key); 55598b9484cSchristos 55698b9484cSchristos /* If the successor is at the root, just return it. */ 55798b9484cSchristos if (comparison > 0) 55898b9484cSchristos return sp->root; 55998b9484cSchristos 56098b9484cSchristos /* Otherwise, find the leftmost element of the right subtree. */ 56198b9484cSchristos node = sp->root->right; 56298b9484cSchristos if (node) 56398b9484cSchristos while (node->left) 56498b9484cSchristos node = node->left; 56598b9484cSchristos 56698b9484cSchristos return node; 56798b9484cSchristos } 56898b9484cSchristos 56998b9484cSchristos /* Call FN, passing it the DATA, for every node in SP, following an 57098b9484cSchristos in-order traversal. If FN every returns a non-zero value, the 57198b9484cSchristos iteration ceases immediately, and the value is returned. 57298b9484cSchristos Otherwise, this function returns 0. */ 57398b9484cSchristos 57498b9484cSchristos int 57598b9484cSchristos splay_tree_foreach (splay_tree sp, splay_tree_foreach_fn fn, void *data) 57698b9484cSchristos { 57798b9484cSchristos return splay_tree_foreach_helper (sp->root, fn, data); 57898b9484cSchristos } 57998b9484cSchristos 58098b9484cSchristos /* Splay-tree comparison function, treating the keys as ints. */ 58198b9484cSchristos 58298b9484cSchristos int 58398b9484cSchristos splay_tree_compare_ints (splay_tree_key k1, splay_tree_key k2) 58498b9484cSchristos { 58598b9484cSchristos if ((int) k1 < (int) k2) 58698b9484cSchristos return -1; 58798b9484cSchristos else if ((int) k1 > (int) k2) 58898b9484cSchristos return 1; 58998b9484cSchristos else 59098b9484cSchristos return 0; 59198b9484cSchristos } 59298b9484cSchristos 59398b9484cSchristos /* Splay-tree comparison function, treating the keys as pointers. */ 59498b9484cSchristos 59598b9484cSchristos int 59698b9484cSchristos splay_tree_compare_pointers (splay_tree_key k1, splay_tree_key k2) 59798b9484cSchristos { 59898b9484cSchristos if ((char*) k1 < (char*) k2) 59998b9484cSchristos return -1; 60098b9484cSchristos else if ((char*) k1 > (char*) k2) 60198b9484cSchristos return 1; 60298b9484cSchristos else 60398b9484cSchristos return 0; 60498b9484cSchristos } 6054559860eSchristos 6064559860eSchristos /* Splay-tree comparison function, treating the keys as strings. */ 6074559860eSchristos 6084559860eSchristos int 6094559860eSchristos splay_tree_compare_strings (splay_tree_key k1, splay_tree_key k2) 6104559860eSchristos { 6114559860eSchristos return strcmp ((char *) k1, (char *) k2); 6124559860eSchristos } 6134559860eSchristos 6144559860eSchristos /* Splay-tree delete function, simply using free. */ 6154559860eSchristos 6164559860eSchristos void 6174559860eSchristos splay_tree_delete_pointers (splay_tree_value value) 6184559860eSchristos { 6194559860eSchristos free ((void *) value); 6204559860eSchristos } 621