Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

splaytree.c

00001 /*****************************************************************************
00002  * splaytree.c:
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: splaytree.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet <[email protected]>
00008  *          code from projectM http://xmms-projectm.sourceforge.net
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 
00026 
00027 /*
00028                 An implementation of top-down splaying
00029                     D. Sleator <[email protected]>
00030                              March 1992
00031 
00032   "Splay trees", or "self-adjusting search trees" are a simple and
00033   efficient data structure for storing an ordered set.  The data
00034   structure consists of a binary tree, without parent pointers, and no
00035   additional fields.  It allows searching, insertion, deletion,
00036   deletemin, deletemax, splitting, joining, and many other operations,
00037   all with amortized logarithmic performance.  Since the trees adapt to
00038   the sequence of requests, their performance on real access patterns is
00039   typically even better.  Splay trees are described in a number of texts
00040   and papers [1,2,3,4,5].
00041 
00042   The code here is adapted from simple top-down splay, at the bottom of
00043   page 669 of [3].  It can be obtained via anonymous ftp from
00044   spade.pc.cs.cmu.edu in directory /usr/sleator/public.
00045 
00046   The chief modification here is that the splay operation works even if the
00047   item being splayed is not in the tree, and even if the tree root of the
00048   tree is NULL.  So the line:
00049 
00050                               t = splay(i, t);
00051 
00052   causes it to search for item with key i in the tree rooted at t.  If it's
00053   there, it is splayed to the root.  If it isn't there, then the node put
00054   at the root is the last one before NULL that would have been reached in a
00055   normal binary search for i.  (It's a neighbor of i in the tree.)  This
00056   allows many other operations to be easily implemented, as shown below.
00057 
00058   [1] "Fundamentals of data structures in C", Horowitz, Sahni,
00059        and Anderson-Freed, Computer Science Press, pp 542-547.
00060 
00061   [2] "Data Structures and Their Algorithms", Lewis and Denenberg,
00062        Harper Collins, 1991, pp 243-251.
00063   [3] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
00064        JACM Volume 32, No 3, July 1985, pp 652-686.
00065   [4] "Data Structure and Algorithm Analysis", Mark Weiss,
00066        Benjamin Cummins, 1992, pp 119-130.
00067   [5] "Data Structures, Algorithms, and Performance", Derick Wood,
00068        Addison-Wesley, 1993, pp 367-375.
00069 
00070   The following code was written by Daniel Sleator, and is released
00071   in the public domain. It has been heavily modified by Carmelo Piccione,
00072   ([email protected]), to suit personal needs, 
00073 */
00074 
00075 #include <stdio.h>
00076 #include <string.h>
00077 #include <stdlib.h>
00078 
00079 #include "common.h"
00080 #include "fatal.h"
00081 
00082 #include "splaytree_types.h"
00083 #include "splaytree.h"
00084 
00085 
00086 
00087 static inline splaynode_t * splay (void * key, splaynode_t * t, int * match_type, int (*compare)());
00088 static inline int free_splaynode(splaynode_t * splaynode, void (*free_key)());
00089 static inline void splay_traverse_helper (void (*func_ptr)(), splaynode_t * splaynode);
00090 static inline splaynode_t * splay_delete_helper(void * key, splaynode_t * t, int (*compare)(), void (*free_key)());
00091 static inline void splay_find_above_min_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)());
00092 static inline void splay_find_below_max_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)());
00093 static inline splaynode_t * new_splaynode(int type, void * key, void * data);
00094 static inline int splay_insert_node(splaynode_t * splaynode, splaytree_t * splaytree);
00095 static inline int splay_rec_size(splaynode_t * splaynode);
00096 
00097 /* Creates a splay tree given a compare key function, copy key function, and free key function.
00098    Ah yes, the wonders of procedural programming */
00099 inline splaytree_t * create_splaytree(int (*compare)(), void * (*copy_key)(), void (*free_key)()) {
00100 
00101   splaytree_t * splaytree;
00102 
00103   /* Allocate memory for the splaytree struct */
00104   if ((splaytree = (splaytree_t*)malloc(sizeof(splaytree_t))) == NULL)
00105     return NULL;
00106 
00107   /* Set struct entries */
00108   splaytree->root = NULL;
00109   splaytree->compare = compare;
00110   splaytree->copy_key = copy_key;
00111   splaytree->free_key = free_key;
00112   
00113   /* Return instantiated splay tree */
00114   return splaytree;
00115 }
00116 
00117 /* Destroys a splay tree */
00118 inline int destroy_splaytree(splaytree_t * splaytree) {
00119 
00120   /* Null argument check */
00121   if (splaytree == NULL)
00122     return FAILURE;
00123 
00124   /* Recursively free all splaynodes in tree */
00125   free_splaynode(splaytree->root, splaytree->free_key);
00126 
00127   /* Free the splaytree struct itself */
00128   free(splaytree);
00129   
00130   /* Done, return success */
00131   return SUCCESS;
00132 
00133 }
00134 
00135 /* Recursively free all the splaynodes */
00136 static inline int free_splaynode(splaynode_t * splaynode, void (*free_key)()) {
00137 
00138   /* Ok if this happens, a recursive base case */
00139   if (splaynode == NULL)
00140     return SUCCESS;
00141 
00142   /* Free left node */
00143   free_splaynode(splaynode->left, free_key);
00144   
00145   /* Free right node */
00146   free_splaynode(splaynode->right, free_key);
00147   
00148   /* Free this node's key */
00149   free_key(splaynode->key);
00150   
00151   /* Note that the data pointers are not freed here.
00152      Should be freed with a splay traversal function */
00153   
00154   /* Free the splaynode structure itself */
00155   free(splaynode);
00156  
00157   /* Finished, return success */
00158   return SUCCESS;
00159 
00160 }
00161 
00162 /* Traverses the entire splay tree with the given function func_ptr */
00163 inline void splay_traverse(void (*func_ptr)(), splaytree_t * splaytree) {
00164 
00165   /* Null argument check */
00166 
00167   if (splaytree == NULL)
00168     return; 
00169   if (func_ptr == NULL)
00170         return;
00171   
00172   /* Call recursive helper function */
00173   splay_traverse_helper(func_ptr, splaytree->root);
00174 
00175   return;
00176 }
00177 
00178 /* Helper function to traverse the entire splaytree */
00179 static inline void splay_traverse_helper (void (*func_ptr)(), splaynode_t * splaynode) {  
00180 
00181   /* Normal if this happens, its a base case of recursion */
00182   if (splaynode == NULL)
00183     return;
00184 
00185   /* Recursively traverse to the left */
00186   splay_traverse_helper(func_ptr, splaynode->left);
00187   
00188   
00189   /* Node is a of regular type, so its ok to perform the function on it */
00190   if (splaynode->type == REGULAR_NODE_TYPE)
00191         func_ptr(splaynode->data);
00192   
00193   /* Node is of symbolic link type, do nothing */
00194   else if (splaynode->type == SYMBOLIC_NODE_TYPE)
00195         ;
00196   
00197   /* Unknown node type */
00198   else
00199     ;
00200   
00201   /* Recursively traverse to the right */
00202   splay_traverse_helper(func_ptr, splaynode->right);
00203 
00204   /* Done */
00205   return;
00206 }
00207 
00208 /* Find the node corresponding to the given key in splaytree, return its data pointer */
00209 inline void * splay_find(void * key, splaytree_t * splaytree) {
00210 
00211   splaynode_t * splaynode;
00212   int match_type;
00213 
00214   if (key == NULL)
00215           return NULL;
00216   
00217   if (splaytree == NULL)
00218           return NULL;
00219   
00220   splaynode = splaytree->root;
00221   
00222   /* Bring the targeted splay node to the top of the splaytree */
00223   splaynode = splay(key, splaynode, &match_type, splaytree->compare);
00224   splaytree->root = splaynode;
00225   
00226   
00227   /* We only want perfect matches, so return null when match isn't perfect */
00228   if (match_type == CLOSEST_MATCH) 
00229     return NULL;
00230 
00231   /* This shouldn't happen because of the match type check, but whatever */
00232   if (splaytree->root == NULL)
00233           return NULL;
00234   
00235   /* Node is a regular type, return its data pointer */
00236   if (splaytree->root->type == REGULAR_NODE_TYPE) /* regular node */
00237         return splaytree->root->data;
00238   
00239   /* If the node is a symlink, pursue one link */
00240   if (splaytree->root->type == SYMBOLIC_NODE_TYPE) /* symbolic node */
00241         return ((splaynode_t*)splaytree->root->data)->data;
00242     
00243   
00244   /* Unknown type */
00245   return NULL;
00246 }
00247 
00248 /* Gets the splaynode that the given key points to */
00249 inline splaynode_t * get_splaynode_of(void * key, splaytree_t * splaytree) {
00250 
00251   splaynode_t * splaynode;
00252   int match_type;
00253   
00254   /* Null argument checks */    
00255   if (splaytree == NULL)
00256           return NULL;
00257   
00258   if (key == NULL)
00259           return NULL;
00260   
00261   splaynode = splaytree->root;
00262 
00263   /* Find the splaynode */
00264   splaynode = splay(key, splaynode, &match_type, splaytree->compare);
00265   splaytree->root = splaynode;
00266  
00267   /* Only perfect matches are valid */
00268   if (match_type == CLOSEST_MATCH)
00269     return NULL;
00270 
00271   /* Return the perfect match splay node */
00272   return splaynode;
00273 }
00274 
00275 /* Finds the desired node, and changes the tree such that it is the root */
00276 static inline splaynode_t * splay (void * key, splaynode_t * t, int * match_type, int (*compare)()) {
00277   
00278 /* Simple top down splay, not requiring key to be in the tree t. 
00279    What it does is described above. */
00280  
00281     splaynode_t N, *l, *r, *y;
00282     *match_type = CLOSEST_MATCH;
00283   
00284         if (t == NULL) return t;
00285     N.left = N.right = NULL;
00286     l = r = &N;
00287   
00288     for (;;) {
00289         if (compare(key, t->key) < 0) {
00290             if (t->left == NULL) break;
00291             if (compare(key, t->left->key) < 0) {
00292                 y = t->left;                           /* rotate right */
00293                 t->left = y->right;
00294                 y->right = t;
00295                 t = y;
00296                 if (t->left == NULL) break;
00297             }
00298             r->left = t;                               /* link right */
00299             r = t;
00300             t = t->left;
00301         } else if (compare(key, t->key) > 0) {
00302             if (t->right == NULL) break;
00303             if (compare(key, t->right->key) > 0) {
00304                 y = t->right;                          /* rotate left */
00305                 t->right = y->left;
00306                 y->left = t;
00307                 t = y;
00308                 if (t->right == NULL) break;
00309             }
00310             l->right = t;                              /* link left */
00311             l = t;
00312             t = t->right;
00313         } else {
00314           *match_type = PERFECT_MATCH;
00315           break;
00316         }
00317     }
00318     l->right = t->left;                                /* assemble */
00319     r->left = t->right;
00320     t->left = N.right;
00321     t->right = N.left;
00322     
00323     return t;
00324 
00325     //return NULL;
00326 }
00327 
00328 /* Deletes a splay node from a splay tree. If the node doesn't exist
00329    then nothing happens */
00330 inline int splay_delete(void * key, splaytree_t * splaytree) {
00331   
00332   splaynode_t * splaynode;
00333 
00334   /* Use helper function to delete the node and return the resulting tree */
00335   if ((splaynode = splay_delete_helper(key, splaytree->root, splaytree->compare, splaytree->free_key)) == NULL)
00336           return FAILURE;
00337   
00338   /* Set new splaytree root equal to the returned splaynode after deletion */
00339   splaytree->root = splaynode;
00340   
00341   /* Finished, no errors */
00342   return SUCCESS;
00343 }
00344 
00345 /* Deletes a splay node */
00346 static inline splaynode_t * splay_delete_helper(void * key, splaynode_t * splaynode, int (*compare)(), void (*free_key)()) {
00347         
00348     splaynode_t * new_root;
00349     int match_type;
00350         
00351         /* Argument check */    
00352     if (splaynode == NULL) 
00353                 return NULL;
00354         
00355     splaynode = splay(key, splaynode, &match_type, compare);
00356         
00357         /* If entry wasn't found, quit here */
00358         if (match_type == CLOSEST_MATCH) 
00359                 return NULL;
00360         
00361         /* If the targeted node's left pointer is null, then set the new root
00362            equal to the splaynode's right child */
00363         if (splaynode->left == NULL) {
00364             new_root = splaynode->right;
00365         } 
00366         
00367         /* Otherwise, do something I don't currently understand */
00368         else {
00369             new_root = splay(key, splaynode->left, &match_type, compare);
00370             new_root->right = splaynode->right;
00371         }
00372 
00373         /* Set splay nodes children pointers to null */
00374         splaynode->left = splaynode->right = NULL;
00375         
00376         /* Free the splaynode (and only this node since its children are now empty */
00377         free_splaynode(splaynode, free_key);
00378         
00379         /* Return the resulting tree */
00380         return new_root;
00381         
00382 }
00383 
00384 /* Create a new splay node type */
00385 static inline splaynode_t * new_splaynode(int type, void * key, void * data) {
00386         splaynode_t * splaynode;        
00387         /* Argument checks */
00388         if (data == NULL)
00389                 return NULL;
00390         
00391         if (key == NULL)
00392                 return NULL;
00393         
00394         /* Creates the new splay node struct */
00395         if ((splaynode = (splaynode_t*)malloc(sizeof(splaynode_t))) == NULL)
00396                 return NULL;
00397         
00398         splaynode->data = data;
00399         splaynode->type = type;
00400         splaynode->key = key;
00401         
00402         /* Return the new splay node */
00403         return splaynode;
00404 }
00405 
00406 /* Inserts a link into the splay tree */
00407 inline int splay_insert_link(void * alias_key, void * orig_key, splaytree_t * splaytree) {
00408 
00409    splaynode_t * splaynode, * data_node;
00410    void * key_clone;
00411 
00412    /* Null arguments */ 
00413    if (splaytree == NULL)
00414                 return FAILURE;
00415    
00416    if (alias_key == NULL)
00417                 return FAILURE;
00418 
00419    if (orig_key == NULL)
00420                 return FAILURE;
00421    
00422    /* Find the splaynode corresponding to the original key */
00423    if ((data_node = get_splaynode_of(orig_key, splaytree)) == NULL)
00424            return FAILURE;
00425    
00426    /* Create a new splay node of symbolic link type */
00427    if ((splaynode = new_splaynode(SYMBOLIC_NODE_TYPE, (key_clone = splaytree->copy_key(alias_key)), data_node)) == NULL) {
00428                 splaytree->free_key(key_clone);
00429                 return OUTOFMEM_ERROR;
00430    }
00431 
00432    /* Insert the splaynode into the given splaytree */
00433    if ((splay_insert_node(splaynode, splaytree)) < 0) {
00434      splaynode->left=splaynode->right = NULL;
00435      free_splaynode(splaynode, splaytree->free_key);
00436      return FAILURE;
00437    }            
00438         
00439    /* Done, return success */
00440    return SUCCESS;
00441 }       
00442 
00443 /* Inserts 'data' into the 'splaytree' paired with the passed 'key' */
00444 inline int splay_insert(void * data, void * key, splaytree_t * splaytree) {
00445 
00446         splaynode_t * splaynode;
00447         void * key_clone;
00448         
00449         /* Null argument checks */
00450         if (splaytree == NULL) {
00451             return FAILURE;
00452         }
00453         
00454         if (key == NULL)
00455                 return FAILURE;
00456         
00457         /* Clone the key argument */
00458         key_clone = splaytree->copy_key(key);
00459 
00460         /* Create a new splaynode (of regular type) */
00461         if ((splaynode = new_splaynode(REGULAR_NODE_TYPE, key_clone, data)) == NULL) {
00462                 splaytree->free_key(key_clone);
00463                 return OUTOFMEM_ERROR;          
00464         }
00465        
00466         
00467         /* Inserts the splaynode into the splaytree */
00468         if (splay_insert_node(splaynode, splaytree) < 0) {
00469           splaynode->left=splaynode->right=NULL;
00470           free_splaynode(splaynode, splaytree->free_key);
00471           return FAILURE;               
00472         }       
00473      
00474 
00475         return SUCCESS;
00476 }
00477 
00478 /* Helper function to insert splaynodes into the splaytree */
00479 static inline int splay_insert_node(splaynode_t * splaynode, splaytree_t * splaytree) {
00480   int match_type;
00481   int cmpval;
00482   void * key;
00483   splaynode_t * t;
00484         
00485   /* Null argument checks */
00486   if (splaytree == NULL)
00487     return FAILURE;
00488 
00489   if (splaynode == NULL)
00490         return FAILURE;
00491   
00492   key = splaynode->key;
00493   
00494   t = splaytree->root; 
00495 
00496 
00497   /* Root is null, insert splaynode here */
00498   if (t == NULL) {
00499         splaynode->left = splaynode->right = NULL;
00500         splaytree->root = splaynode;
00501         return SUCCESS;
00502 
00503   }
00504   
00505   t = splay(key, t, &match_type, splaytree->compare);
00506   
00507   if ((cmpval = splaytree->compare(key,t->key)) < 0) {
00508         splaynode->left = t->left;
00509         splaynode->right = t;
00510         t->left = NULL;
00511         splaytree->root = splaynode;
00512         return SUCCESS;
00513 
00514   } 
00515 
00516   else if (cmpval > 0) {
00517         splaynode->right = t->right;
00518         splaynode->left = t;
00519         t->right = NULL; 
00520         splaytree->root = splaynode;
00521         return SUCCESS;
00522    } 
00523    
00524    /* Item already exists in tree, don't reinsert */
00525   else {
00526     
00527     return FAILURE;
00528   }
00529 }
00530 
00531 /* Returns the 'maximum' key that is less than the given key in the splaytree */
00532 inline void * splay_find_below_max(void * key, splaytree_t * splaytree) {
00533         
00534         void * closest_key;
00535         
00536         if (splaytree == NULL)
00537                 return NULL;
00538         if (splaytree->root == NULL)
00539                 return NULL;
00540         if (key == NULL)
00541                 return NULL;
00542         
00543         closest_key = NULL;
00544         
00545         splay_find_below_max_helper(key, &closest_key, splaytree->root, splaytree->compare);
00546 
00547         if (closest_key == NULL) return NULL;
00548         return splay_find(closest_key, splaytree);
00549 }
00550 
00551 
00552 /* Returns the 'minimum' key that is greater than the given key in the splaytree */
00553 inline void * splay_find_above_min(void * key, splaytree_t * splaytree) {
00554         
00555         void * closest_key;
00556         
00557         if (splaytree == NULL)
00558                 return NULL;
00559         if (splaytree->root == NULL)
00560                 return NULL;
00561         if (key == NULL)
00562                 return NULL;
00563         closest_key = NULL;
00564         
00565         splay_find_above_min_helper(key, &closest_key, splaytree->root, splaytree->compare);
00566 
00567         if (closest_key == NULL) { 
00568                 return NULL;
00569         }
00570         
00571         return splay_find(closest_key, splaytree);
00572 }
00573 
00574 /* Helper function */
00575 static inline void splay_find_below_max_helper(void * min_key, void ** closest_key, splaynode_t * root, int (*compare)()) {
00576 
00577                 /* Empty root, return*/ 
00578                 if (root == NULL)
00579                         return;
00580                         
00581                 /* The root key is less than the previously found closest key.
00582                    Also try to make the key non null if the value is less than the max key */
00583                 
00584                 if ((*closest_key == NULL) || (compare(root->key, *closest_key) < 0)) {
00585                         
00586                         /*  The root key is less than the given max key, so this is the
00587                                 smallest change from the given max key */
00588                         if (compare(root->key, min_key) > 0) {
00589                                 
00590                                 *closest_key = root->key;
00591                                 
00592                                 /* Look right again in case even a greater key exists that is 
00593                                    still less than the given max key */
00594                                 splay_find_below_max_helper(min_key, closest_key, root->left, compare);
00595                         }
00596                         
00597                         /* The root key is greater than the given max key, and greater than 
00598                            the closest key, so search left */
00599                         else {
00600                                 splay_find_below_max_helper(min_key, closest_key, root->right, compare);                                
00601                         }       
00602                 }       
00603                 
00604                 /* The root key is less than the found closest key, search right */
00605                 else {
00606                                 splay_find_below_max_helper(min_key, closest_key, root->left, compare);                         
00607                 }
00608         
00609 }
00610 
00611 /* Helper function */
00612 static inline void splay_find_above_min_helper(void * max_key, void ** closest_key, splaynode_t * root, int (*compare)()) {
00613 
00614                 /* Empty root, stop */  
00615                 if (root == NULL)
00616                         return;
00617                         
00618                 /* The root key is greater than the previously found closest key.
00619                    Also try to make the key non null if the value is less than the min key */
00620                 
00621                 if ((*closest_key == NULL) || (compare(root->key, *closest_key) > 0)) {
00622                         
00623                         /*  The root key is greater than the given min key, so this is the
00624                                 smallest change from the given min key */
00625                         if (compare(root->key, max_key) < 0) {
00626                                 
00627                                 *closest_key = root->key;
00628                                 
00629                            /* Look left again in case even a smaller key exists that is 
00630                                   still greater than the given min key */
00631                                 splay_find_above_min_helper(max_key, closest_key, root->right, compare);
00632                         }
00633                         
00634                         /* The root key is less than the given min key, and less than 
00635                            the closest key, so search right */
00636                         else {
00637                                 splay_find_above_min_helper(max_key, closest_key, root->left, compare);                         
00638                         }       
00639                 }       
00640                 
00641                 /* The root key is greater than the found closest key, search left */
00642                 else {
00643                                 splay_find_above_min_helper(max_key, closest_key, root->right, compare);                                
00644                 }
00645 }       
00646 
00647 /* Find the minimum entry of the splay tree */
00648 inline void * splay_find_min(splaytree_t * t) {
00649 
00650         splaynode_t * splaynode;
00651         
00652         if (t == NULL)
00653                 return NULL;
00654         if (t->root == NULL)
00655                 return NULL;
00656         
00657         splaynode = t->root;
00658         
00659         while (splaynode->left != NULL)
00660                 splaynode= splaynode->left;
00661         
00662         return splaynode->data;
00663 }
00664 
00665 
00666 /* Find the maximum entry of the splay tree */
00667 inline void * splay_find_max(splaytree_t * t) {
00668 
00669         splaynode_t * splaynode;
00670         
00671         if (t == NULL)
00672                 return NULL;
00673         if (t->root == NULL)
00674                 return NULL;
00675         
00676         splaynode = t->root;
00677          
00678         while (splaynode->right != NULL) {
00679           printf("data:%d\n", *(int*)splaynode->key);
00680                 splaynode = splaynode->right;
00681         }
00682         return splaynode->data;
00683 }
00684 
00685 inline int splay_size(splaytree_t * t) {
00686 
00687         if (t == NULL)
00688           return 0;
00689         if (t->root == NULL)
00690           return 0;
00691         
00692         return splay_rec_size(t->root);
00693          
00694 }
00695 
00696 static inline int splay_rec_size(splaynode_t * splaynode) {
00697 
00698   if (!splaynode)
00699     return 0;
00700 
00701   return 1 + splay_rec_size(splaynode->left) + splay_rec_size(splaynode->right);
00702 
00703 }

Generated on Tue Dec 20 10:14:59 2005 for vlc-0.8.4a by  doxygen 1.4.2