Home | History | Annotate | Line # | Download | only in libiberty
      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