1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@videolan.org>
8 * code from projectM http://xmms-projectm.sourceforge.net
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
28 An implementation of top-down splaying
29 D. Sleator <sleator@cs.cmu.edu>
32 "Splay trees", or "self-adjusting search trees" are a simple and
33 efficient data structure for storing an ordered set. The data
34 structure consists of a binary tree, without parent pointers, and no
35 additional fields. It allows searching, insertion, deletion,
36 deletemin, deletemax, splitting, joining, and many other operations,
37 all with amortized logarithmic performance. Since the trees adapt to
38 the sequence of requests, their performance on real access patterns is
39 typically even better. Splay trees are described in a number of texts
40 and papers [1,2,3,4,5].
42 The code here is adapted from simple top-down splay, at the bottom of
43 page 669 of [3]. It can be obtained via anonymous ftp from
44 spade.pc.cs.cmu.edu in directory /usr/sleator/public.
46 The chief modification here is that the splay operation works even if the
47 item being splayed is not in the tree, and even if the tree root of the
48 tree is NULL. So the line:
52 causes it to search for item with key i in the tree rooted at t. If it's
53 there, it is splayed to the root. If it isn't there, then the node put
54 at the root is the last one before NULL that would have been reached in a
55 normal binary search for i. (It's a neighbor of i in the tree.) This
56 allows many other operations to be easily implemented, as shown below.
58 [1] "Fundamentals of data structures in C", Horowitz, Sahni,
59 and Anderson-Freed, Computer Science Press, pp 542-547.
61 [2] "Data Structures and Their Algorithms", Lewis and Denenberg,
62 Harper Collins, 1991, pp 243-251.
63 [3] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
64 JACM Volume 32, No 3, July 1985, pp 652-686.
65 [4] "Data Structure and Algorithm Analysis", Mark Weiss,
66 Benjamin Cummins, 1992, pp 119-130.
67 [5] "Data Structures, Algorithms, and Performance", Derick Wood,
68 Addison-Wesley, 1993, pp 367-375.
70 The following code was written by Daniel Sleator, and is released
71 in the public domain. It has been heavily modified by Carmelo Piccione,
72 (cep@andrew.cmu.edu), to suit personal needs,
79 #include "splaytree_types.h"
80 #include "splaytree.h"
84 static inline splaynode_t * splay (void * key, splaynode_t * t, int * match_type, int (*compare)());
85 static inline int free_splaynode(splaynode_t * splaynode, void (*free_key)());
86 static inline void splay_traverse_helper (void (*func_ptr)(), splaynode_t * splaynode);
87 static inline splaynode_t * splay_delete_helper(void * key, splaynode_t * t, int (*compare)(), void (*free_key)());
88 static inline void splay_find_above_min_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)());
89 static inline void splay_find_below_max_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)());
90 static inline splaynode_t * new_splaynode(int type, void * key, void * data);
91 static inline int splay_insert_node(splaynode_t * splaynode, splaytree_t * splaytree);
92 static inline int splay_rec_size(splaynode_t * splaynode);
94 /* Creates a splay tree given a compare key function, copy key function, and free key function.
95 Ah yes, the wonders of procedural programming */
96 inline splaytree_t * create_splaytree(int (*compare)(), void * (*copy_key)(), void (*free_key)()) {
98 splaytree_t * splaytree;
100 /* Allocate memory for the splaytree struct */
101 if ((splaytree = (splaytree_t*)malloc(sizeof(splaytree_t))) == NULL)
104 /* Set struct entries */
105 splaytree->root = NULL;
106 splaytree->compare = compare;
107 splaytree->copy_key = copy_key;
108 splaytree->free_key = free_key;
110 /* Return instantiated splay tree */
114 /* Destroys a splay tree */
115 inline int destroy_splaytree(splaytree_t * splaytree) {
117 /* Null argument check */
118 if (splaytree == NULL)
121 /* Recursively free all splaynodes in tree */
122 free_splaynode(splaytree->root, splaytree->free_key);
124 /* Free the splaytree struct itself */
127 /* Done, return success */
132 /* Recursively free all the splaynodes */
133 static inline int free_splaynode(splaynode_t * splaynode, void (*free_key)()) {
135 /* Ok if this happens, a recursive base case */
136 if (splaynode == NULL)
140 free_splaynode(splaynode->left, free_key);
142 /* Free right node */
143 free_splaynode(splaynode->right, free_key);
145 /* Free this node's key */
146 free_key(splaynode->key);
148 /* Note that the data pointers are not freed here.
149 Should be freed with a splay traversal function */
151 /* Free the splaynode structure itself */
154 /* Finished, return success */
159 /* Traverses the entire splay tree with the given function func_ptr */
160 inline void splay_traverse(void (*func_ptr)(), splaytree_t * splaytree) {
162 /* Null argument check */
164 if (splaytree == NULL)
166 if (func_ptr == NULL)
169 /* Call recursive helper function */
170 splay_traverse_helper(func_ptr, splaytree->root);
175 /* Helper function to traverse the entire splaytree */
176 static inline void splay_traverse_helper (void (*func_ptr)(), splaynode_t * splaynode) {
178 /* Normal if this happens, its a base case of recursion */
179 if (splaynode == NULL)
182 /* Recursively traverse to the left */
183 splay_traverse_helper(func_ptr, splaynode->left);
186 /* Node is a of regular type, so its ok to perform the function on it */
187 if (splaynode->type == REGULAR_NODE_TYPE)
188 func_ptr(splaynode->data);
190 /* Node is of symbolic link type, do nothing */
191 else if (splaynode->type == SYMBOLIC_NODE_TYPE)
194 /* Unknown node type */
198 /* Recursively traverse to the right */
199 splay_traverse_helper(func_ptr, splaynode->right);
205 /* Find the node corresponding to the given key in splaytree, return its data pointer */
206 inline void * splay_find(void * key, splaytree_t * splaytree) {
208 splaynode_t * splaynode;
214 if (splaytree == NULL)
217 splaynode = splaytree->root;
219 /* Bring the targeted splay node to the top of the splaytree */
220 splaynode = splay(key, splaynode, &match_type, splaytree->compare);
221 splaytree->root = splaynode;
224 /* We only want perfect matches, so return null when match isn't perfect */
225 if (match_type == CLOSEST_MATCH)
228 /* This shouldn't happen because of the match type check, but whatever */
229 if (splaytree->root == NULL)
232 /* Node is a regular type, return its data pointer */
233 if (splaytree->root->type == REGULAR_NODE_TYPE) /* regular node */
234 return splaytree->root->data;
236 /* If the node is a symlink, pursue one link */
237 if (splaytree->root->type == SYMBOLIC_NODE_TYPE) /* symbolic node */
238 return ((splaynode_t*)splaytree->root->data)->data;
245 /* Gets the splaynode that the given key points to */
246 inline splaynode_t * get_splaynode_of(void * key, splaytree_t * splaytree) {
248 splaynode_t * splaynode;
251 /* Null argument checks */
252 if (splaytree == NULL)
258 splaynode = splaytree->root;
260 /* Find the splaynode */
261 splaynode = splay(key, splaynode, &match_type, splaytree->compare);
262 splaytree->root = splaynode;
264 /* Only perfect matches are valid */
265 if (match_type == CLOSEST_MATCH)
268 /* Return the perfect match splay node */
272 /* Finds the desired node, and changes the tree such that it is the root */
273 static inline splaynode_t * splay (void * key, splaynode_t * t, int * match_type, int (*compare)()) {
275 /* Simple top down splay, not requiring key to be in the tree t.
276 What it does is described above. */
278 splaynode_t N, *l, *r, *y;
279 *match_type = CLOSEST_MATCH;
281 if (t == NULL) return t;
282 N.left = N.right = NULL;
286 if (compare(key, t->key) < 0) {
287 if (t->left == NULL) break;
288 if (compare(key, t->left->key) < 0) {
289 y = t->left; /* rotate right */
293 if (t->left == NULL) break;
295 r->left = t; /* link right */
298 } else if (compare(key, t->key) > 0) {
299 if (t->right == NULL) break;
300 if (compare(key, t->right->key) > 0) {
301 y = t->right; /* rotate left */
305 if (t->right == NULL) break;
307 l->right = t; /* link left */
311 *match_type = PERFECT_MATCH;
315 l->right = t->left; /* assemble */
325 /* Deletes a splay node from a splay tree. If the node doesn't exist
326 then nothing happens */
327 inline int splay_delete(void * key, splaytree_t * splaytree) {
329 splaynode_t * splaynode;
331 /* Use helper function to delete the node and return the resulting tree */
332 if ((splaynode = splay_delete_helper(key, splaytree->root, splaytree->compare, splaytree->free_key)) == NULL)
335 /* Set new splaytree root equal to the returned splaynode after deletion */
336 splaytree->root = splaynode;
338 /* Finished, no errors */
342 /* Deletes a splay node */
343 static inline splaynode_t * splay_delete_helper(void * key, splaynode_t * splaynode, int (*compare)(), void (*free_key)()) {
345 splaynode_t * new_root;
349 if (splaynode == NULL)
352 splaynode = splay(key, splaynode, &match_type, compare);
354 /* If entry wasn't found, quit here */
355 if (match_type == CLOSEST_MATCH)
358 /* If the targeted node's left pointer is null, then set the new root
359 equal to the splaynode's right child */
360 if (splaynode->left == NULL) {
361 new_root = splaynode->right;
364 /* Otherwise, do something I don't currently understand */
366 new_root = splay(key, splaynode->left, &match_type, compare);
367 new_root->right = splaynode->right;
370 /* Set splay nodes children pointers to null */
371 splaynode->left = splaynode->right = NULL;
373 /* Free the splaynode (and only this node since its children are now empty */
374 free_splaynode(splaynode, free_key);
376 /* Return the resulting tree */
381 /* Create a new splay node type */
382 static inline splaynode_t * new_splaynode(int type, void * key, void * data) {
383 splaynode_t * splaynode;
384 /* Argument checks */
391 /* Creates the new splay node struct */
392 if ((splaynode = (splaynode_t*)malloc(sizeof(splaynode_t))) == NULL)
395 splaynode->data = data;
396 splaynode->type = type;
397 splaynode->key = key;
399 /* Return the new splay node */
403 /* Inserts a link into the splay tree */
404 inline int splay_insert_link(void * alias_key, void * orig_key, splaytree_t * splaytree) {
406 splaynode_t * splaynode, * data_node;
410 if (splaytree == NULL)
413 if (alias_key == NULL)
416 if (orig_key == NULL)
419 /* Find the splaynode corresponding to the original key */
420 if ((data_node = get_splaynode_of(orig_key, splaytree)) == NULL)
423 /* Create a new splay node of symbolic link type */
424 if ((splaynode = new_splaynode(SYMBOLIC_NODE_TYPE, (key_clone = splaytree->copy_key(alias_key)), data_node)) == NULL) {
425 splaytree->free_key(key_clone);
426 return OUTOFMEM_ERROR;
429 /* Insert the splaynode into the given splaytree */
430 if ((splay_insert_node(splaynode, splaytree)) < 0) {
431 splaynode->left=splaynode->right = NULL;
432 free_splaynode(splaynode, splaytree->free_key);
436 /* Done, return success */
440 /* Inserts 'data' into the 'splaytree' paired with the passed 'key' */
441 inline int splay_insert(void * data, void * key, splaytree_t * splaytree) {
443 splaynode_t * splaynode;
446 /* Null argument checks */
447 if (splaytree == NULL) {
454 /* Clone the key argument */
455 key_clone = splaytree->copy_key(key);
457 /* Create a new splaynode (of regular type) */
458 if ((splaynode = new_splaynode(REGULAR_NODE_TYPE, key_clone, data)) == NULL) {
459 splaytree->free_key(key_clone);
460 return OUTOFMEM_ERROR;
464 /* Inserts the splaynode into the splaytree */
465 if (splay_insert_node(splaynode, splaytree) < 0) {
466 splaynode->left=splaynode->right=NULL;
467 free_splaynode(splaynode, splaytree->free_key);
475 /* Helper function to insert splaynodes into the splaytree */
476 static inline int splay_insert_node(splaynode_t * splaynode, splaytree_t * splaytree) {
482 /* Null argument checks */
483 if (splaytree == NULL)
486 if (splaynode == NULL)
489 key = splaynode->key;
494 /* Root is null, insert splaynode here */
496 splaynode->left = splaynode->right = NULL;
497 splaytree->root = splaynode;
502 t = splay(key, t, &match_type, splaytree->compare);
504 if ((cmpval = splaytree->compare(key,t->key)) < 0) {
505 splaynode->left = t->left;
506 splaynode->right = t;
508 splaytree->root = splaynode;
513 else if (cmpval > 0) {
514 splaynode->right = t->right;
517 splaytree->root = splaynode;
521 /* Item already exists in tree, don't reinsert */
528 /* Returns the 'maximum' key that is less than the given key in the splaytree */
529 inline void * splay_find_below_max(void * key, splaytree_t * splaytree) {
533 if (splaytree == NULL)
535 if (splaytree->root == NULL)
542 splay_find_below_max_helper(key, &closest_key, splaytree->root, splaytree->compare);
544 if (closest_key == NULL) return NULL;
545 return splay_find(closest_key, splaytree);
549 /* Returns the 'minimum' key that is greater than the given key in the splaytree */
550 inline void * splay_find_above_min(void * key, splaytree_t * splaytree) {
554 if (splaytree == NULL)
556 if (splaytree->root == NULL)
562 splay_find_above_min_helper(key, &closest_key, splaytree->root, splaytree->compare);
564 if (closest_key == NULL) {
568 return splay_find(closest_key, splaytree);
571 /* Helper function */
572 static inline void splay_find_below_max_helper(void * min_key, void ** closest_key, splaynode_t * root, int (*compare)()) {
574 /* Empty root, return*/
578 /* The root key is less than the previously found closest key.
579 Also try to make the key non null if the value is less than the max key */
581 if ((*closest_key == NULL) || (compare(root->key, *closest_key) < 0)) {
583 /* The root key is less than the given max key, so this is the
584 smallest change from the given max key */
585 if (compare(root->key, min_key) > 0) {
587 *closest_key = root->key;
589 /* Look right again in case even a greater key exists that is
590 still less than the given max key */
591 splay_find_below_max_helper(min_key, closest_key, root->left, compare);
594 /* The root key is greater than the given max key, and greater than
595 the closest key, so search left */
597 splay_find_below_max_helper(min_key, closest_key, root->right, compare);
601 /* The root key is less than the found closest key, search right */
603 splay_find_below_max_helper(min_key, closest_key, root->left, compare);
608 /* Helper function */
609 static inline void splay_find_above_min_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)()) {
611 /* Empty root, stop */
615 /* The root key is greater than the previously found closest key.
616 Also try to make the key non null if the value is less than the min key */
618 if ((*closest_key == NULL) || (compare(root->key, *closest_key) > 0)) {
620 /* The root key is greater than the given min key, so this is the
621 smallest change from the given min key */
622 if (compare(root->key, max_key) < 0) {
624 *closest_key = root->key;
626 /* Look left again in case even a smaller key exists that is
627 still greater than the given min key */
628 splay_find_above_min_helper(max_key, closest_key, root->right, compare);
631 /* The root key is less than the given min key, and less than
632 the closest key, so search right */
634 splay_find_above_min_helper(max_key, closest_key, root->left, compare);
638 /* The root key is greater than the found closest key, search left */
640 splay_find_above_min_helper(max_key, closest_key, root->right, compare);
644 /* Find the minimum entry of the splay tree */
645 inline void * splay_find_min(splaytree_t * t) {
647 splaynode_t * splaynode;
656 while (splaynode->left != NULL)
657 splaynode= splaynode->left;
659 return splaynode->data;
663 /* Find the maximum entry of the splay tree */
664 inline void * splay_find_max(splaytree_t * t) {
666 splaynode_t * splaynode;
675 while (splaynode->right != NULL) {
676 printf("data:%d\n", *(int*)splaynode->key);
677 splaynode = splaynode->right;
679 return splaynode->data;
682 inline int splay_size(splaytree_t * t) {
689 return splay_rec_size(t->root);
693 static inline int splay_rec_size(splaynode_t * splaynode) {
698 return 1 + splay_rec_size(splaynode->left) + splay_rec_size(splaynode->right);