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