1 |
/* A splay-tree datatype. |
/* A splay-tree datatype. |
2 |
Copyright (C) 1998 Free Software Foundation, Inc. |
Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc. |
3 |
Contributed by Mark Mitchell (mark@markmitchell.com). |
Contributed by Mark Mitchell (mark@markmitchell.com). |
4 |
|
|
5 |
This file is part of GNU CC. |
This file is part of GNU CC. |
32 |
#include <stdlib.h> |
#include <stdlib.h> |
33 |
#endif |
#endif |
34 |
|
|
35 |
|
#include <stdio.h> |
36 |
|
|
37 |
#include "libiberty.h" |
#include "libiberty.h" |
38 |
#include "splay-tree.h" |
#include "splay-tree.h" |
39 |
|
|
237 |
splay_tree_delete_key_fn delete_key_fn; |
splay_tree_delete_key_fn delete_key_fn; |
238 |
splay_tree_delete_value_fn delete_value_fn; |
splay_tree_delete_value_fn delete_value_fn; |
239 |
{ |
{ |
240 |
splay_tree sp = (splay_tree) xmalloc (sizeof (struct splay_tree)); |
splay_tree sp = (splay_tree) xmalloc (sizeof (struct splay_tree_s)); |
241 |
sp->root = 0; |
sp->root = 0; |
242 |
sp->comp = compare_fn; |
sp->comp = compare_fn; |
243 |
sp->delete_key = delete_key_fn; |
sp->delete_key = delete_key_fn; |
258 |
|
|
259 |
/* Insert a new node (associating KEY with DATA) into SP. If a |
/* Insert a new node (associating KEY with DATA) into SP. If a |
260 |
previous node with the indicated KEY exists, its data is replaced |
previous node with the indicated KEY exists, its data is replaced |
261 |
with the new value. */ |
with the new value. Returns the new node. */ |
262 |
|
|
263 |
void |
splay_tree_node |
264 |
splay_tree_insert (sp, key, value) |
splay_tree_insert (sp, key, value) |
265 |
splay_tree sp; |
splay_tree sp; |
266 |
splay_tree_key key; |
splay_tree_key key; |
267 |
splay_tree_value value; |
splay_tree_value value; |
268 |
{ |
{ |
269 |
int comparison; |
int comparison = 0; |
270 |
|
|
271 |
splay_tree_splay (sp, key); |
splay_tree_splay (sp, key); |
272 |
|
|
286 |
/* Create a new node, and insert it at the root. */ |
/* Create a new node, and insert it at the root. */ |
287 |
splay_tree_node node; |
splay_tree_node node; |
288 |
|
|
289 |
node = (splay_tree_node) xmalloc (sizeof (struct splay_tree_node)); |
node = (splay_tree_node) xmalloc (sizeof (struct splay_tree_node_s)); |
290 |
node->key = key; |
node->key = key; |
291 |
node->value = value; |
node->value = value; |
292 |
|
|
305 |
node->right->left = 0; |
node->right->left = 0; |
306 |
} |
} |
307 |
|
|
308 |
sp->root = node; |
sp->root = node; |
309 |
} |
} |
310 |
|
|
311 |
|
return sp->root; |
312 |
|
} |
313 |
|
|
314 |
|
/* Remove KEY from SP. It is not an error if it did not exist. */ |
315 |
|
|
316 |
|
void |
317 |
|
splay_tree_remove (sp, key) |
318 |
|
splay_tree sp; |
319 |
|
splay_tree_key key; |
320 |
|
{ |
321 |
|
splay_tree_splay (sp, key); |
322 |
|
|
323 |
|
if (sp->root && (*sp->comp) (sp->root->key, key) == 0) |
324 |
|
{ |
325 |
|
splay_tree_node left, right; |
326 |
|
|
327 |
|
left = sp->root->left; |
328 |
|
right = sp->root->right; |
329 |
|
|
330 |
|
/* Delete the root node itself. */ |
331 |
|
if (sp->delete_value) |
332 |
|
(*sp->delete_value) (sp->root->value); |
333 |
|
free (sp->root); |
334 |
|
|
335 |
|
/* One of the children is now the root. Doesn't matter much |
336 |
|
which, so long as we preserve the properties of the tree. */ |
337 |
|
if (left) |
338 |
|
{ |
339 |
|
sp->root = left; |
340 |
|
|
341 |
|
/* If there was a right child as well, hang it off the |
342 |
|
right-most leaf of the left child. */ |
343 |
|
if (right) |
344 |
|
{ |
345 |
|
while (left->right) |
346 |
|
left = left->right; |
347 |
|
left->right = right; |
348 |
|
} |
349 |
|
} |
350 |
|
else |
351 |
|
sp->root = right; |
352 |
|
} |
353 |
} |
} |
354 |
|
|
355 |
/* Lookup KEY in SP, returning VALUE if present, and NULL |
/* Lookup KEY in SP, returning VALUE if present, and NULL |
368 |
return 0; |
return 0; |
369 |
} |
} |
370 |
|
|
371 |
|
/* Return the node in SP with the greatest key. */ |
372 |
|
|
373 |
|
splay_tree_node |
374 |
|
splay_tree_max (sp) |
375 |
|
splay_tree sp; |
376 |
|
{ |
377 |
|
splay_tree_node n = sp->root; |
378 |
|
|
379 |
|
if (!n) |
380 |
|
return NULL; |
381 |
|
|
382 |
|
while (n->right) |
383 |
|
n = n->right; |
384 |
|
|
385 |
|
return n; |
386 |
|
} |
387 |
|
|
388 |
|
/* Return the node in SP with the smallest key. */ |
389 |
|
|
390 |
|
splay_tree_node |
391 |
|
splay_tree_min (sp) |
392 |
|
splay_tree sp; |
393 |
|
{ |
394 |
|
splay_tree_node n = sp->root; |
395 |
|
|
396 |
|
if (!n) |
397 |
|
return NULL; |
398 |
|
|
399 |
|
while (n->left) |
400 |
|
n = n->left; |
401 |
|
|
402 |
|
return n; |
403 |
|
} |
404 |
|
|
405 |
|
/* Return the immediate predecessor KEY, or NULL if there is no |
406 |
|
predecessor. KEY need not be present in the tree. */ |
407 |
|
|
408 |
|
splay_tree_node |
409 |
|
splay_tree_predecessor (sp, key) |
410 |
|
splay_tree sp; |
411 |
|
splay_tree_key key; |
412 |
|
{ |
413 |
|
int comparison; |
414 |
|
splay_tree_node node; |
415 |
|
|
416 |
|
/* If the tree is empty, there is certainly no predecessor. */ |
417 |
|
if (!sp->root) |
418 |
|
return NULL; |
419 |
|
|
420 |
|
/* Splay the tree around KEY. That will leave either the KEY |
421 |
|
itself, its predecessor, or its successor at the root. */ |
422 |
|
splay_tree_splay (sp, key); |
423 |
|
comparison = (*sp->comp)(sp->root->key, key); |
424 |
|
|
425 |
|
/* If the predecessor is at the root, just return it. */ |
426 |
|
if (comparison < 0) |
427 |
|
return sp->root; |
428 |
|
|
429 |
|
/* Otherwise, find the leftmost element of the right subtree. */ |
430 |
|
node = sp->root->left; |
431 |
|
if (node) |
432 |
|
while (node->right) |
433 |
|
node = node->right; |
434 |
|
|
435 |
|
return node; |
436 |
|
} |
437 |
|
|
438 |
|
/* Return the immediate successor KEY, or NULL if there is no |
439 |
|
predecessor. KEY need not be present in the tree. */ |
440 |
|
|
441 |
|
splay_tree_node |
442 |
|
splay_tree_successor (sp, key) |
443 |
|
splay_tree sp; |
444 |
|
splay_tree_key key; |
445 |
|
{ |
446 |
|
int comparison; |
447 |
|
splay_tree_node node; |
448 |
|
|
449 |
|
/* If the tree is empty, there is certainly no predecessor. */ |
450 |
|
if (!sp->root) |
451 |
|
return NULL; |
452 |
|
|
453 |
|
/* Splay the tree around KEY. That will leave either the KEY |
454 |
|
itself, its predecessor, or its successor at the root. */ |
455 |
|
splay_tree_splay (sp, key); |
456 |
|
comparison = (*sp->comp)(sp->root->key, key); |
457 |
|
|
458 |
|
/* If the successor is at the root, just return it. */ |
459 |
|
if (comparison > 0) |
460 |
|
return sp->root; |
461 |
|
|
462 |
|
/* Otherwise, find the rightmost element of the left subtree. */ |
463 |
|
node = sp->root->right; |
464 |
|
if (node) |
465 |
|
while (node->left) |
466 |
|
node = node->left; |
467 |
|
|
468 |
|
return node; |
469 |
|
} |
470 |
|
|
471 |
/* Call FN, passing it the DATA, for every node in SP, following an |
/* Call FN, passing it the DATA, for every node in SP, following an |
472 |
in-order traversal. If FN every returns a non-zero value, the |
in-order traversal. If FN every returns a non-zero value, the |
473 |
iteration ceases immediately, and the value is returned. |
iteration ceases immediately, and the value is returned. |