70 |
if (sp->delete_value) |
if (sp->delete_value) |
71 |
(*sp->delete_value)(node->value); |
(*sp->delete_value)(node->value); |
72 |
|
|
73 |
free ((char*) node); |
(*sp->deallocate) ((char*) node, sp->allocate_data); |
74 |
} |
} |
75 |
|
|
76 |
/* Help splay SP around KEY. PARENT and GRANDPARENT are the parent |
/* Help splay SP around KEY. PARENT and GRANDPARENT are the parent |
227 |
return splay_tree_foreach_helper (sp, node->right, fn, data); |
return splay_tree_foreach_helper (sp, node->right, fn, data); |
228 |
} |
} |
229 |
|
|
230 |
|
|
231 |
|
/* An allocator and deallocator based on xmalloc. */ |
232 |
|
static void * |
233 |
|
splay_tree_xmalloc_allocate (size, data) |
234 |
|
int size; |
235 |
|
void *data ATTRIBUTE_UNUSED; |
236 |
|
{ |
237 |
|
return (void *) xmalloc (size); |
238 |
|
} |
239 |
|
|
240 |
|
static void |
241 |
|
splay_tree_xmalloc_deallocate (object, data) |
242 |
|
void *object; |
243 |
|
void *data ATTRIBUTE_UNUSED; |
244 |
|
{ |
245 |
|
free (object); |
246 |
|
} |
247 |
|
|
248 |
|
|
249 |
/* Allocate a new splay tree, using COMPARE_FN to compare nodes, |
/* Allocate a new splay tree, using COMPARE_FN to compare nodes, |
250 |
DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate |
DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate |
251 |
values. */ |
values. Use xmalloc to allocate the splay tree structure, and any |
252 |
|
nodes added. */ |
253 |
|
|
254 |
splay_tree |
splay_tree |
255 |
splay_tree_new (compare_fn, delete_key_fn, delete_value_fn) |
splay_tree_new (compare_fn, delete_key_fn, delete_value_fn) |
257 |
splay_tree_delete_key_fn delete_key_fn; |
splay_tree_delete_key_fn delete_key_fn; |
258 |
splay_tree_delete_value_fn delete_value_fn; |
splay_tree_delete_value_fn delete_value_fn; |
259 |
{ |
{ |
260 |
splay_tree sp = (splay_tree) xmalloc (sizeof (struct splay_tree_s)); |
return (splay_tree_new_with_allocator |
261 |
|
(compare_fn, delete_key_fn, delete_value_fn, |
262 |
|
splay_tree_xmalloc_allocate, splay_tree_xmalloc_deallocate, 0)); |
263 |
|
} |
264 |
|
|
265 |
|
|
266 |
|
/* Allocate a new splay tree, using COMPARE_FN to compare nodes, |
267 |
|
DELETE_KEY_FN to deallocate keys, and DELETE_VALUE_FN to deallocate |
268 |
|
values. */ |
269 |
|
|
270 |
|
splay_tree |
271 |
|
splay_tree_new_with_allocator (compare_fn, delete_key_fn, delete_value_fn, |
272 |
|
allocate_fn, deallocate_fn, allocate_data) |
273 |
|
splay_tree_compare_fn compare_fn; |
274 |
|
splay_tree_delete_key_fn delete_key_fn; |
275 |
|
splay_tree_delete_value_fn delete_value_fn; |
276 |
|
splay_tree_allocate_fn allocate_fn; |
277 |
|
splay_tree_deallocate_fn deallocate_fn; |
278 |
|
void *allocate_data; |
279 |
|
{ |
280 |
|
splay_tree sp = (splay_tree) (*allocate_fn) (sizeof (struct splay_tree_s), |
281 |
|
allocate_data); |
282 |
sp->root = 0; |
sp->root = 0; |
283 |
sp->comp = compare_fn; |
sp->comp = compare_fn; |
284 |
sp->delete_key = delete_key_fn; |
sp->delete_key = delete_key_fn; |
285 |
sp->delete_value = delete_value_fn; |
sp->delete_value = delete_value_fn; |
286 |
|
sp->allocate = allocate_fn; |
287 |
|
sp->deallocate = deallocate_fn; |
288 |
|
sp->allocate_data = allocate_data; |
289 |
|
|
290 |
return sp; |
return sp; |
291 |
} |
} |
297 |
splay_tree sp; |
splay_tree sp; |
298 |
{ |
{ |
299 |
splay_tree_delete_helper (sp, sp->root); |
splay_tree_delete_helper (sp, sp->root); |
300 |
free ((char*) sp); |
(*sp->deallocate) ((char*) sp, sp->allocate_data); |
301 |
} |
} |
302 |
|
|
303 |
/* Insert a new node (associating KEY with DATA) into SP. If a |
/* Insert a new node (associating KEY with DATA) into SP. If a |
330 |
/* Create a new node, and insert it at the root. */ |
/* Create a new node, and insert it at the root. */ |
331 |
splay_tree_node node; |
splay_tree_node node; |
332 |
|
|
333 |
node = (splay_tree_node) xmalloc (sizeof (struct splay_tree_node_s)); |
node = ((splay_tree_node) |
334 |
|
(*sp->allocate) (sizeof (struct splay_tree_node_s), |
335 |
|
sp->allocate_data)); |
336 |
node->key = key; |
node->key = key; |
337 |
node->value = value; |
node->value = value; |
338 |
|
|
376 |
/* Delete the root node itself. */ |
/* Delete the root node itself. */ |
377 |
if (sp->delete_value) |
if (sp->delete_value) |
378 |
(*sp->delete_value) (sp->root->value); |
(*sp->delete_value) (sp->root->value); |
379 |
free (sp->root); |
(*sp->deallocate) (sp->root, sp->allocate_data); |
380 |
|
|
381 |
/* One of the children is now the root. Doesn't matter much |
/* One of the children is now the root. Doesn't matter much |
382 |
which, so long as we preserve the properties of the tree. */ |
which, so long as we preserve the properties of the tree. */ |
472 |
if (comparison < 0) |
if (comparison < 0) |
473 |
return sp->root; |
return sp->root; |
474 |
|
|
475 |
/* Otherwise, find the leftmost element of the right subtree. */ |
/* Otherwise, find the rightmost element of the left subtree. */ |
476 |
node = sp->root->left; |
node = sp->root->left; |
477 |
if (node) |
if (node) |
478 |
while (node->right) |
while (node->right) |
482 |
} |
} |
483 |
|
|
484 |
/* Return the immediate successor KEY, or NULL if there is no |
/* Return the immediate successor KEY, or NULL if there is no |
485 |
predecessor. KEY need not be present in the tree. */ |
successor. KEY need not be present in the tree. */ |
486 |
|
|
487 |
splay_tree_node |
splay_tree_node |
488 |
splay_tree_successor (sp, key) |
splay_tree_successor (sp, key) |
492 |
int comparison; |
int comparison; |
493 |
splay_tree_node node; |
splay_tree_node node; |
494 |
|
|
495 |
/* If the tree is empty, there is certainly no predecessor. */ |
/* If the tree is empty, there is certainly no successor. */ |
496 |
if (!sp->root) |
if (!sp->root) |
497 |
return NULL; |
return NULL; |
498 |
|
|
505 |
if (comparison > 0) |
if (comparison > 0) |
506 |
return sp->root; |
return sp->root; |
507 |
|
|
508 |
/* Otherwise, find the rightmost element of the left subtree. */ |
/* Otherwise, find the leftmost element of the right subtree. */ |
509 |
node = sp->root->right; |
node = sp->root->right; |
510 |
if (node) |
if (node) |
511 |
while (node->left) |
while (node->left) |