xref: /openbsd-src/gnu/lib/libiberty/src/splay-tree.c (revision 150b7e42cfa21e6546d96ae514ca23e80d970ac7)
100bf4279Sespie /* A splay-tree datatype.
237c53322Sespie    Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
300bf4279Sespie    Contributed by Mark Mitchell (mark@markmitchell.com).
400bf4279Sespie 
500bf4279Sespie This file is part of GNU CC.
600bf4279Sespie 
700bf4279Sespie GNU CC is free software; you can redistribute it and/or modify it
800bf4279Sespie under the terms of the GNU General Public License as published by
900bf4279Sespie the Free Software Foundation; either version 2, or (at your option)
1000bf4279Sespie any later version.
1100bf4279Sespie 
1200bf4279Sespie GNU CC is distributed in the hope that it will be useful, but
1300bf4279Sespie WITHOUT ANY WARRANTY; without even the implied warranty of
1400bf4279Sespie MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1500bf4279Sespie General Public License for more details.
1600bf4279Sespie 
1700bf4279Sespie You should have received a copy of the GNU General Public License
1800bf4279Sespie along with GNU CC; see the file COPYING.  If not, write to
19*150b7e42Smiod the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20*150b7e42Smiod Boston, MA 02110-1301, USA.  */
2100bf4279Sespie 
2200bf4279Sespie /* For an easily readable description of splay-trees, see:
2300bf4279Sespie 
2400bf4279Sespie      Lewis, Harry R. and Denenberg, Larry.  Data Structures and Their
2500bf4279Sespie      Algorithms.  Harper-Collins, Inc.  1991.  */
2600bf4279Sespie 
2700bf4279Sespie #ifdef HAVE_CONFIG_H
2800bf4279Sespie #include "config.h"
2900bf4279Sespie #endif
3000bf4279Sespie 
3100bf4279Sespie #ifdef HAVE_STDLIB_H
3200bf4279Sespie #include <stdlib.h>
3300bf4279Sespie #endif
3400bf4279Sespie 
3537c53322Sespie #include <stdio.h>
3637c53322Sespie 
3700bf4279Sespie #include "libiberty.h"
3800bf4279Sespie #include "splay-tree.h"
3900bf4279Sespie 
40*150b7e42Smiod static void splay_tree_delete_helper (splay_tree, splay_tree_node);
41*150b7e42Smiod static inline void rotate_left (splay_tree_node *,
42*150b7e42Smiod 				splay_tree_node, splay_tree_node);
43*150b7e42Smiod static inline void rotate_right (splay_tree_node *,
44*150b7e42Smiod 				splay_tree_node, splay_tree_node);
45*150b7e42Smiod static void splay_tree_splay (splay_tree, splay_tree_key);
46*150b7e42Smiod static int splay_tree_foreach_helper (splay_tree, splay_tree_node,
47*150b7e42Smiod                                       splay_tree_foreach_fn, void*);
4800bf4279Sespie 
4900bf4279Sespie /* Deallocate NODE (a member of SP), and all its sub-trees.  */
5000bf4279Sespie 
5100bf4279Sespie static void
splay_tree_delete_helper(splay_tree sp,splay_tree_node node)52*150b7e42Smiod splay_tree_delete_helper (splay_tree sp, splay_tree_node node)
5300bf4279Sespie {
54*150b7e42Smiod   splay_tree_node pending = 0;
55*150b7e42Smiod   splay_tree_node active = 0;
56*150b7e42Smiod 
5700bf4279Sespie   if (!node)
5800bf4279Sespie     return;
5900bf4279Sespie 
60*150b7e42Smiod #define KDEL(x)  if (sp->delete_key) (*sp->delete_key)(x);
61*150b7e42Smiod #define VDEL(x)  if (sp->delete_value) (*sp->delete_value)(x);
6200bf4279Sespie 
63*150b7e42Smiod   KDEL (node->key);
64*150b7e42Smiod   VDEL (node->value);
6500bf4279Sespie 
66*150b7e42Smiod   /* We use the "key" field to hold the "next" pointer.  */
67*150b7e42Smiod   node->key = (splay_tree_key)pending;
68*150b7e42Smiod   pending = (splay_tree_node)node;
69*150b7e42Smiod 
70*150b7e42Smiod   /* Now, keep processing the pending list until there aren't any
71*150b7e42Smiod      more.  This is a little more complicated than just recursing, but
72*150b7e42Smiod      it doesn't toast the stack for large trees.  */
73*150b7e42Smiod 
74*150b7e42Smiod   while (pending)
75*150b7e42Smiod     {
76*150b7e42Smiod       active = pending;
77*150b7e42Smiod       pending = 0;
78*150b7e42Smiod       while (active)
79*150b7e42Smiod 	{
80*150b7e42Smiod 	  splay_tree_node temp;
81*150b7e42Smiod 
82*150b7e42Smiod 	  /* active points to a node which has its key and value
83*150b7e42Smiod 	     deallocated, we just need to process left and right.  */
84*150b7e42Smiod 
85*150b7e42Smiod 	  if (active->left)
86*150b7e42Smiod 	    {
87*150b7e42Smiod 	      KDEL (active->left->key);
88*150b7e42Smiod 	      VDEL (active->left->value);
89*150b7e42Smiod 	      active->left->key = (splay_tree_key)pending;
90*150b7e42Smiod 	      pending = (splay_tree_node)(active->left);
91*150b7e42Smiod 	    }
92*150b7e42Smiod 	  if (active->right)
93*150b7e42Smiod 	    {
94*150b7e42Smiod 	      KDEL (active->right->key);
95*150b7e42Smiod 	      VDEL (active->right->value);
96*150b7e42Smiod 	      active->right->key = (splay_tree_key)pending;
97*150b7e42Smiod 	      pending = (splay_tree_node)(active->right);
9800bf4279Sespie 	    }
9900bf4279Sespie 
100*150b7e42Smiod 	  temp = active;
101*150b7e42Smiod 	  active = (splay_tree_node)(temp->key);
102*150b7e42Smiod 	  (*sp->deallocate) ((char*) temp, sp->allocate_data);
103*150b7e42Smiod 	}
104*150b7e42Smiod     }
105*150b7e42Smiod #undef KDEL
106*150b7e42Smiod #undef VDEL
10700bf4279Sespie }
10800bf4279Sespie 
109*150b7e42Smiod /* Rotate the edge joining the left child N with its parent P.  PP is the
110*150b7e42Smiod    grandparents pointer to P.  */
11100bf4279Sespie 
112*150b7e42Smiod static inline void
rotate_left(splay_tree_node * pp,splay_tree_node p,splay_tree_node n)113*150b7e42Smiod rotate_left (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
11400bf4279Sespie {
115*150b7e42Smiod   splay_tree_node tmp;
116*150b7e42Smiod   tmp = n->right;
11700bf4279Sespie   n->right = p;
118*150b7e42Smiod   p->left = tmp;
119*150b7e42Smiod   *pp = n;
12000bf4279Sespie }
12100bf4279Sespie 
122*150b7e42Smiod /* Rotate the edge joining the right child N with its parent P.  PP is the
123*150b7e42Smiod    grandparents pointer to P.  */
124*150b7e42Smiod 
125*150b7e42Smiod static inline void
rotate_right(splay_tree_node * pp,splay_tree_node p,splay_tree_node n)126*150b7e42Smiod rotate_right (splay_tree_node *pp, splay_tree_node p, splay_tree_node n)
127*150b7e42Smiod {
128*150b7e42Smiod   splay_tree_node tmp;
129*150b7e42Smiod   tmp = n->left;
13000bf4279Sespie   n->left = p;
131*150b7e42Smiod   p->right = tmp;
132*150b7e42Smiod   *pp = n;
13300bf4279Sespie }
13400bf4279Sespie 
135*150b7e42Smiod /* Bottom up splay of key.  */
13600bf4279Sespie 
13700bf4279Sespie static void
splay_tree_splay(splay_tree sp,splay_tree_key key)138*150b7e42Smiod splay_tree_splay (splay_tree sp, splay_tree_key key)
13900bf4279Sespie {
14000bf4279Sespie   if (sp->root == 0)
14100bf4279Sespie     return;
14200bf4279Sespie 
143*150b7e42Smiod   do {
144*150b7e42Smiod     int cmp1, cmp2;
145*150b7e42Smiod     splay_tree_node n, c;
146*150b7e42Smiod 
147*150b7e42Smiod     n = sp->root;
148*150b7e42Smiod     cmp1 = (*sp->comp) (key, n->key);
149*150b7e42Smiod 
150*150b7e42Smiod     /* Found.  */
151*150b7e42Smiod     if (cmp1 == 0)
152*150b7e42Smiod       return;
153*150b7e42Smiod 
154*150b7e42Smiod     /* Left or right?  If no child, then we're done.  */
155*150b7e42Smiod     if (cmp1 < 0)
156*150b7e42Smiod       c = n->left;
157*150b7e42Smiod     else
158*150b7e42Smiod       c = n->right;
159*150b7e42Smiod     if (!c)
160*150b7e42Smiod       return;
161*150b7e42Smiod 
162*150b7e42Smiod     /* Next one left or right?  If found or no child, we're done
163*150b7e42Smiod        after one rotation.  */
164*150b7e42Smiod     cmp2 = (*sp->comp) (key, c->key);
165*150b7e42Smiod     if (cmp2 == 0
166*150b7e42Smiod         || (cmp2 < 0 && !c->left)
167*150b7e42Smiod         || (cmp2 > 0 && !c->right))
168*150b7e42Smiod       {
169*150b7e42Smiod 	if (cmp1 < 0)
170*150b7e42Smiod 	  rotate_left (&sp->root, n, c);
171*150b7e42Smiod 	else
172*150b7e42Smiod 	  rotate_right (&sp->root, n, c);
173*150b7e42Smiod         return;
174*150b7e42Smiod       }
175*150b7e42Smiod 
176*150b7e42Smiod     /* Now we have the four cases of double-rotation.  */
177*150b7e42Smiod     if (cmp1 < 0 && cmp2 < 0)
178*150b7e42Smiod       {
179*150b7e42Smiod 	rotate_left (&n->left, c, c->left);
180*150b7e42Smiod 	rotate_left (&sp->root, n, n->left);
181*150b7e42Smiod       }
182*150b7e42Smiod     else if (cmp1 > 0 && cmp2 > 0)
183*150b7e42Smiod       {
184*150b7e42Smiod 	rotate_right (&n->right, c, c->right);
185*150b7e42Smiod 	rotate_right (&sp->root, n, n->right);
186*150b7e42Smiod       }
187*150b7e42Smiod     else if (cmp1 < 0 && cmp2 > 0)
188*150b7e42Smiod       {
189*150b7e42Smiod 	rotate_right (&n->left, c, c->right);
190*150b7e42Smiod 	rotate_left (&sp->root, n, n->left);
191*150b7e42Smiod       }
192*150b7e42Smiod     else if (cmp1 > 0 && cmp2 < 0)
193*150b7e42Smiod       {
194*150b7e42Smiod 	rotate_left (&n->right, c, c->left);
195*150b7e42Smiod 	rotate_right (&sp->root, n, n->right);
196*150b7e42Smiod       }
197*150b7e42Smiod   } while (1);
19800bf4279Sespie }
19900bf4279Sespie 
20000bf4279Sespie /* Call FN, passing it the DATA, for every node below NODE, all of
20100bf4279Sespie    which are from SP, following an in-order traversal.  If FN every
20200bf4279Sespie    returns a non-zero value, the iteration ceases immediately, and the
20300bf4279Sespie    value is returned.  Otherwise, this function returns 0.  */
20400bf4279Sespie 
20500bf4279Sespie static int
splay_tree_foreach_helper(splay_tree sp,splay_tree_node node,splay_tree_foreach_fn fn,void * data)206*150b7e42Smiod splay_tree_foreach_helper (splay_tree sp, splay_tree_node node,
207*150b7e42Smiod                            splay_tree_foreach_fn fn, void *data)
20800bf4279Sespie {
20900bf4279Sespie   int val;
21000bf4279Sespie 
21100bf4279Sespie   if (!node)
21200bf4279Sespie     return 0;
21300bf4279Sespie 
21400bf4279Sespie   val = splay_tree_foreach_helper (sp, node->left, fn, data);
21500bf4279Sespie   if (val)
21600bf4279Sespie     return val;
21700bf4279Sespie 
21800bf4279Sespie   val = (*fn)(node, data);
21900bf4279Sespie   if (val)
22000bf4279Sespie     return val;
22100bf4279Sespie 
22200bf4279Sespie   return splay_tree_foreach_helper (sp, node->right, fn, data);
22300bf4279Sespie }
22400bf4279Sespie 
22537c53322Sespie 
22637c53322Sespie /* An allocator and deallocator based on xmalloc.  */
22737c53322Sespie static void *
splay_tree_xmalloc_allocate(int size,void * data ATTRIBUTE_UNUSED)228*150b7e42Smiod splay_tree_xmalloc_allocate (int size, void *data ATTRIBUTE_UNUSED)
22937c53322Sespie {
23037c53322Sespie   return (void *) xmalloc (size);
23137c53322Sespie }
23237c53322Sespie 
23337c53322Sespie static void
splay_tree_xmalloc_deallocate(void * object,void * data ATTRIBUTE_UNUSED)234*150b7e42Smiod splay_tree_xmalloc_deallocate (void *object, void *data ATTRIBUTE_UNUSED)
23537c53322Sespie {
23637c53322Sespie   free (object);
23737c53322Sespie }
23837c53322Sespie 
23937c53322Sespie 
24000bf4279Sespie /* Allocate a new splay tree, using COMPARE_FN to compare nodes,
24100bf4279Sespie    DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
24237c53322Sespie    values.  Use xmalloc to allocate the splay tree structure, and any
24337c53322Sespie    nodes added.  */
24400bf4279Sespie 
24500bf4279Sespie splay_tree
splay_tree_new(splay_tree_compare_fn compare_fn,splay_tree_delete_key_fn delete_key_fn,splay_tree_delete_value_fn delete_value_fn)246*150b7e42Smiod splay_tree_new (splay_tree_compare_fn compare_fn,
247*150b7e42Smiod                 splay_tree_delete_key_fn delete_key_fn,
248*150b7e42Smiod                 splay_tree_delete_value_fn delete_value_fn)
24900bf4279Sespie {
25037c53322Sespie   return (splay_tree_new_with_allocator
25137c53322Sespie           (compare_fn, delete_key_fn, delete_value_fn,
25237c53322Sespie            splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate, 0));
25337c53322Sespie }
25437c53322Sespie 
25537c53322Sespie 
25637c53322Sespie /* Allocate a new splay tree, using COMPARE_FN to compare nodes,
25737c53322Sespie    DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate
25837c53322Sespie    values.  */
25937c53322Sespie 
26037c53322Sespie splay_tree
splay_tree_new_with_allocator(splay_tree_compare_fn compare_fn,splay_tree_delete_key_fn delete_key_fn,splay_tree_delete_value_fn delete_value_fn,splay_tree_allocate_fn allocate_fn,splay_tree_deallocate_fn deallocate_fn,void * allocate_data)261*150b7e42Smiod splay_tree_new_with_allocator (splay_tree_compare_fn compare_fn,
262*150b7e42Smiod                                splay_tree_delete_key_fn delete_key_fn,
263*150b7e42Smiod                                splay_tree_delete_value_fn delete_value_fn,
264*150b7e42Smiod                                splay_tree_allocate_fn allocate_fn,
265*150b7e42Smiod                                splay_tree_deallocate_fn deallocate_fn,
266*150b7e42Smiod                                void *allocate_data)
26737c53322Sespie {
26837c53322Sespie   splay_tree sp = (splay_tree) (*allocate_fn) (sizeof (struct splay_tree_s),
26937c53322Sespie                                                allocate_data);
27000bf4279Sespie   sp->root = 0;
27100bf4279Sespie   sp->comp = compare_fn;
27200bf4279Sespie   sp->delete_key = delete_key_fn;
27300bf4279Sespie   sp->delete_value = delete_value_fn;
27437c53322Sespie   sp->allocate = allocate_fn;
27537c53322Sespie   sp->deallocate = deallocate_fn;
27637c53322Sespie   sp->allocate_data = allocate_data;
27700bf4279Sespie 
27800bf4279Sespie   return sp;
27900bf4279Sespie }
28000bf4279Sespie 
28100bf4279Sespie /* Deallocate SP.  */
28200bf4279Sespie 
28300bf4279Sespie void
splay_tree_delete(splay_tree sp)284*150b7e42Smiod splay_tree_delete (splay_tree sp)
28500bf4279Sespie {
28600bf4279Sespie   splay_tree_delete_helper (sp, sp->root);
28737c53322Sespie   (*sp->deallocate) ((char*) sp, sp->allocate_data);
28800bf4279Sespie }
28900bf4279Sespie 
29000bf4279Sespie /* Insert a new node (associating KEY with DATA) into SP.  If a
29100bf4279Sespie    previous node with the indicated KEY exists, its data is replaced
29200bf4279Sespie    with the new value.  Returns the new node.  */
29300bf4279Sespie 
29400bf4279Sespie splay_tree_node
splay_tree_insert(splay_tree sp,splay_tree_key key,splay_tree_value value)295*150b7e42Smiod splay_tree_insert (splay_tree sp, splay_tree_key key, splay_tree_value value)
29600bf4279Sespie {
29700bf4279Sespie   int comparison = 0;
29800bf4279Sespie 
29900bf4279Sespie   splay_tree_splay (sp, key);
30000bf4279Sespie 
30100bf4279Sespie   if (sp->root)
30200bf4279Sespie     comparison = (*sp->comp)(sp->root->key, key);
30300bf4279Sespie 
30400bf4279Sespie   if (sp->root && comparison == 0)
30500bf4279Sespie     {
30600bf4279Sespie       /* If the root of the tree already has the indicated KEY, just
30700bf4279Sespie 	 replace the value with VALUE.  */
30800bf4279Sespie       if (sp->delete_value)
30900bf4279Sespie 	(*sp->delete_value)(sp->root->value);
31000bf4279Sespie       sp->root->value = value;
31100bf4279Sespie     }
31200bf4279Sespie   else
31300bf4279Sespie     {
31400bf4279Sespie       /* Create a new node, and insert it at the root.  */
31500bf4279Sespie       splay_tree_node node;
31600bf4279Sespie 
31737c53322Sespie       node = ((splay_tree_node)
31837c53322Sespie               (*sp->allocate) (sizeof (struct splay_tree_node_s),
31937c53322Sespie                                sp->allocate_data));
32000bf4279Sespie       node->key = key;
32100bf4279Sespie       node->value = value;
32200bf4279Sespie 
32300bf4279Sespie       if (!sp->root)
32400bf4279Sespie 	node->left = node->right = 0;
32500bf4279Sespie       else if (comparison < 0)
32600bf4279Sespie 	{
32700bf4279Sespie 	  node->left = sp->root;
32800bf4279Sespie 	  node->right = node->left->right;
32900bf4279Sespie 	  node->left->right = 0;
33000bf4279Sespie 	}
33100bf4279Sespie       else
33200bf4279Sespie 	{
33300bf4279Sespie 	  node->right = sp->root;
33400bf4279Sespie 	  node->left = node->right->left;
33500bf4279Sespie 	  node->right->left = 0;
33600bf4279Sespie 	}
33700bf4279Sespie 
33800bf4279Sespie       sp->root = node;
33900bf4279Sespie     }
34000bf4279Sespie 
34100bf4279Sespie   return sp->root;
34200bf4279Sespie }
34300bf4279Sespie 
34437c53322Sespie /* Remove KEY from SP.  It is not an error if it did not exist.  */
34537c53322Sespie 
34637c53322Sespie void
splay_tree_remove(splay_tree sp,splay_tree_key key)347*150b7e42Smiod splay_tree_remove (splay_tree sp, splay_tree_key key)
34837c53322Sespie {
34937c53322Sespie   splay_tree_splay (sp, key);
35037c53322Sespie 
35137c53322Sespie   if (sp->root && (*sp->comp) (sp->root->key, key) == 0)
35237c53322Sespie     {
35337c53322Sespie       splay_tree_node left, right;
35437c53322Sespie 
35537c53322Sespie       left = sp->root->left;
35637c53322Sespie       right = sp->root->right;
35737c53322Sespie 
35837c53322Sespie       /* Delete the root node itself.  */
35937c53322Sespie       if (sp->delete_value)
36037c53322Sespie 	(*sp->delete_value) (sp->root->value);
36137c53322Sespie       (*sp->deallocate) (sp->root, sp->allocate_data);
36237c53322Sespie 
36337c53322Sespie       /* One of the children is now the root.  Doesn't matter much
36437c53322Sespie 	 which, so long as we preserve the properties of the tree.  */
36537c53322Sespie       if (left)
36637c53322Sespie 	{
36737c53322Sespie 	  sp->root = left;
36837c53322Sespie 
36937c53322Sespie 	  /* If there was a right child as well, hang it off the
37037c53322Sespie 	     right-most leaf of the left child.  */
37137c53322Sespie 	  if (right)
37237c53322Sespie 	    {
37337c53322Sespie 	      while (left->right)
37437c53322Sespie 		left = left->right;
37537c53322Sespie 	      left->right = right;
37637c53322Sespie 	    }
37737c53322Sespie 	}
37837c53322Sespie       else
37937c53322Sespie 	sp->root = right;
38037c53322Sespie     }
38137c53322Sespie }
38237c53322Sespie 
38300bf4279Sespie /* Lookup KEY in SP, returning VALUE if present, and NULL
38400bf4279Sespie    otherwise.  */
38500bf4279Sespie 
38600bf4279Sespie splay_tree_node
splay_tree_lookup(splay_tree sp,splay_tree_key key)387*150b7e42Smiod splay_tree_lookup (splay_tree sp, splay_tree_key key)
38800bf4279Sespie {
38900bf4279Sespie   splay_tree_splay (sp, key);
39000bf4279Sespie 
39100bf4279Sespie   if (sp->root && (*sp->comp)(sp->root->key, key) == 0)
39200bf4279Sespie     return sp->root;
39300bf4279Sespie   else
39400bf4279Sespie     return 0;
39500bf4279Sespie }
39600bf4279Sespie 
39737c53322Sespie /* Return the node in SP with the greatest key.  */
39837c53322Sespie 
39937c53322Sespie splay_tree_node
splay_tree_max(splay_tree sp)400*150b7e42Smiod splay_tree_max (splay_tree sp)
40137c53322Sespie {
40237c53322Sespie   splay_tree_node n = sp->root;
40337c53322Sespie 
40437c53322Sespie   if (!n)
40537c53322Sespie     return NULL;
40637c53322Sespie 
40737c53322Sespie   while (n->right)
40837c53322Sespie     n = n->right;
40937c53322Sespie 
41037c53322Sespie   return n;
41137c53322Sespie }
41237c53322Sespie 
41337c53322Sespie /* Return the node in SP with the smallest key.  */
41437c53322Sespie 
41537c53322Sespie splay_tree_node
splay_tree_min(splay_tree sp)416*150b7e42Smiod splay_tree_min (splay_tree sp)
41737c53322Sespie {
41837c53322Sespie   splay_tree_node n = sp->root;
41937c53322Sespie 
42037c53322Sespie   if (!n)
42137c53322Sespie     return NULL;
42237c53322Sespie 
42337c53322Sespie   while (n->left)
42437c53322Sespie     n = n->left;
42537c53322Sespie 
42637c53322Sespie   return n;
42737c53322Sespie }
42837c53322Sespie 
42937c53322Sespie /* Return the immediate predecessor KEY, or NULL if there is no
43037c53322Sespie    predecessor.  KEY need not be present in the tree.  */
43137c53322Sespie 
43237c53322Sespie splay_tree_node
splay_tree_predecessor(splay_tree sp,splay_tree_key key)433*150b7e42Smiod splay_tree_predecessor (splay_tree sp, splay_tree_key key)
43437c53322Sespie {
43537c53322Sespie   int comparison;
43637c53322Sespie   splay_tree_node node;
43737c53322Sespie 
43837c53322Sespie   /* If the tree is empty, there is certainly no predecessor.  */
43937c53322Sespie   if (!sp->root)
44037c53322Sespie     return NULL;
44137c53322Sespie 
44237c53322Sespie   /* Splay the tree around KEY.  That will leave either the KEY
44337c53322Sespie      itself, its predecessor, or its successor at the root.  */
44437c53322Sespie   splay_tree_splay (sp, key);
44537c53322Sespie   comparison = (*sp->comp)(sp->root->key, key);
44637c53322Sespie 
44737c53322Sespie   /* If the predecessor is at the root, just return it.  */
44837c53322Sespie   if (comparison < 0)
44937c53322Sespie     return sp->root;
45037c53322Sespie 
451*150b7e42Smiod   /* Otherwise, find the rightmost element of the left subtree.  */
45237c53322Sespie   node = sp->root->left;
45337c53322Sespie   if (node)
45437c53322Sespie     while (node->right)
45537c53322Sespie       node = node->right;
45637c53322Sespie 
45737c53322Sespie   return node;
45837c53322Sespie }
45937c53322Sespie 
46037c53322Sespie /* Return the immediate successor KEY, or NULL if there is no
46137c53322Sespie    successor.  KEY need not be present in the tree.  */
46237c53322Sespie 
46337c53322Sespie splay_tree_node
splay_tree_successor(splay_tree sp,splay_tree_key key)464*150b7e42Smiod splay_tree_successor (splay_tree sp, splay_tree_key key)
46537c53322Sespie {
46637c53322Sespie   int comparison;
46737c53322Sespie   splay_tree_node node;
46837c53322Sespie 
46937c53322Sespie   /* If the tree is empty, there is certainly no successor.  */
47037c53322Sespie   if (!sp->root)
47137c53322Sespie     return NULL;
47237c53322Sespie 
47337c53322Sespie   /* Splay the tree around KEY.  That will leave either the KEY
47437c53322Sespie      itself, its predecessor, or its successor at the root.  */
47537c53322Sespie   splay_tree_splay (sp, key);
47637c53322Sespie   comparison = (*sp->comp)(sp->root->key, key);
47737c53322Sespie 
47837c53322Sespie   /* If the successor is at the root, just return it.  */
47937c53322Sespie   if (comparison > 0)
48037c53322Sespie     return sp->root;
48137c53322Sespie 
482*150b7e42Smiod   /* Otherwise, find the leftmost element of the right subtree.  */
48337c53322Sespie   node = sp->root->right;
48437c53322Sespie   if (node)
48537c53322Sespie     while (node->left)
48637c53322Sespie       node = node->left;
48737c53322Sespie 
48837c53322Sespie   return node;
48937c53322Sespie }
49037c53322Sespie 
49100bf4279Sespie /* Call FN, passing it the DATA, for every node in SP, following an
49200bf4279Sespie    in-order traversal.  If FN every returns a non-zero value, the
49300bf4279Sespie    iteration ceases immediately, and the value is returned.
49400bf4279Sespie    Otherwise, this function returns 0.  */
49500bf4279Sespie 
49600bf4279Sespie int
splay_tree_foreach(splay_tree sp,splay_tree_foreach_fn fn,void * data)497*150b7e42Smiod splay_tree_foreach (splay_tree sp, splay_tree_foreach_fn fn, void *data)
49800bf4279Sespie {
49900bf4279Sespie   return splay_tree_foreach_helper (sp, sp->root, fn, data);
50000bf4279Sespie }
50100bf4279Sespie 
50200bf4279Sespie /* Splay-tree comparison function, treating the keys as ints.  */
50300bf4279Sespie 
50400bf4279Sespie int
splay_tree_compare_ints(splay_tree_key k1,splay_tree_key k2)505*150b7e42Smiod splay_tree_compare_ints (splay_tree_key k1, splay_tree_key k2)
50600bf4279Sespie {
50700bf4279Sespie   if ((int) k1 < (int) k2)
50800bf4279Sespie     return -1;
50900bf4279Sespie   else if ((int) k1 > (int) k2)
51000bf4279Sespie     return 1;
51100bf4279Sespie   else
51200bf4279Sespie     return 0;
51300bf4279Sespie }
51400bf4279Sespie 
51500bf4279Sespie /* Splay-tree comparison function, treating the keys as pointers.  */
51600bf4279Sespie 
51700bf4279Sespie int
splay_tree_compare_pointers(splay_tree_key k1,splay_tree_key k2)518*150b7e42Smiod splay_tree_compare_pointers (splay_tree_key k1, splay_tree_key k2)
51900bf4279Sespie {
52000bf4279Sespie   if ((char*) k1 < (char*) k2)
52100bf4279Sespie     return -1;
52200bf4279Sespie   else if ((char*) k1 > (char*) k2)
52300bf4279Sespie     return 1;
52400bf4279Sespie   else
52500bf4279Sespie     return 0;
52600bf4279Sespie }
527