/* psplay.h - probabilistic splay tree Copyright (C) 2004, 2005, 2006, Christian Thaeter Copyright (C) Lumiera.org 2007, 2008, Christian Thaeter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef PSPLAY_H #define PSPLAY_H #include #include /** * @file * Probabilistic splay trees * A splay trees is self-optimizing (in contrast to self-balancing) datastructure. * We introduce here a probabilistic bottom up approach which reduces the splay costs. * Without affecting the performance. The randomization gives also some insurance that * worst case situations are extremely unlikely. * Tree nodes are very small (just 2 pointers) and are intrusively placed into the users * datastructure. */ /** * Type and handle for a psplay tree node * This node have to be placed inside users data. */ typedef struct psplaynode_struct psplaynode; typedef psplaynode* PSplaynode; struct psplaynode_struct { PSplaynode left; PSplaynode right; }; #define PSPLAYNODE_INITIALIZER {NULL, NULL} /** * Function use to compare keys * @param a first key * @param b second key * @return shall return -1/0/1 when a is less than/equal to/biggier than b. */ typedef int (*psplay_cmp_fn)(const void* a, const void* b); /** * Destructor for user defined data * Called when an element got removed from a splay tree. * @param node pointer to the intrusive node inside the users datastructure * The user is responsible for casting 'node' back to his real datastructure (maybe with OFFSET_OF()), * free all resources associated with it and finally free the datastructure itself. */ typedef void (*psplay_delete_fn)(PSplaynode node); /** * Retrieve the key from a user datastructure * @param node pointer to the intrusive node inside the users datastructure * This functiom must return a pointer to the key under which the user stores his data. */ typedef const void* (*psplay_key_fn)(const PSplaynode node); /** * Type and handle for a psplay root structure * This structure shall be treated opaque, its only defined in the header to allow * one to integrate it directly instead referencing it. */ typedef struct psplay_struct psplay; typedef psplay* PSplay; struct psplay_struct { PSplaynode tree; /* the tree */ PSplaynode* found_parent; /* maybe direct parent of last found node, used for fast remove */ psplay_cmp_fn cmp; psplay_key_fn key; psplay_delete_fn delete; size_t elem_cnt; unsigned log2; /* roughly log2 of the elem_cnt*/ }; /** * Number of elements in tree * @param self pointer to the tree * @return number of elements */ static inline size_t psplay_nelements (PSplay self) { return self->elem_cnt; }; /** * Initialize a splay tree * @param self pointer to the psplay structure * @param cmp user supplied compare function * @param key user supplied function to retrieve a key * @param delete user supplied destructor function or NULL if no destructor is necessary * @return self */ PSplay psplay_init (PSplay self, psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn delete); /** * Destroy a splay tree * Frees all elements and associated resources of a splay tree * @param self pointer to the psplay structure * @return self */ PSplay psplay_destroy (PSplay self); /** * Allocate a splay tree * @param cmp user supplied compare function * @param key user supplied function to retrieve a key * @param delete user supplied destructor function or NULL if no destructor is necessary * @return allcoated splay tree or NULL on error */ PSplay psplay_new (psplay_cmp_fn cmp, psplay_key_fn key, psplay_delete_fn delete); /** * Delete a splay tree * Frees all elements and associated resources of a splay tree and then itseld * @param self pointer to the psplay structure */ void psplay_delete (PSplay self); /** * Initialize a splay tree node * The user has to place this nodes within his datastructure and must * initialize them before using them. * @param self pointer to the node to be initialized * @return self */ PSplaynode psplaynode_init (PSplaynode self); /** * Insert a element into a splay tree * @param self pointer to the splay tree * @param node pointer to the node to be inserted * @param splayfactor weight for the probabilistic splaying, * 0 disables the splaying, 100 is the expected normal value * use 100 when in doubt * @return self or NULL when a node with same key already in the tree */ PSplaynode psplay_insert (PSplay self, PSplaynode node, int splayfactor); /** * Find a element in a splay tree * @param self pointer to the splay tree * @param key pointer to the key to be searched * @param splayfactor weight for the probabilistic splaying, * 0 disables the splaying, 100 is the expected normal value * @return found node or NULL if the key was not found in the tree */ PSplaynode psplay_find (PSplay self, const void* key, int splayfactor); /** * Remove a node from a splay tree * @param self pointer to the splay tree * @param node node to be removed * @return pointer to the removed node * removal is optimized for the case where one call it immediately after one did a * psplay_find() as last operation on that tree */ PSplaynode psplay_remove (PSplay self, PSplaynode node); /** * Remove a node by key from a splay tree * @param self pointer to the splay tree * @param key key of the node to be removed * @return pointer to the removed node */ PSplaynode psplay_remove_key (PSplay self, void* key); /** * Delete a node from a splay tree * @param self pointer to the splay tree * @param node node to be removed * Calls the registered delete handler, frees all resources. */ void psplay_delete_node (PSplay self, PSplaynode node); /** * Delete a node by key from a splay tree * @param self pointer to the splay tree * @param key key of the node to be removed * Calls the registered delete handler, frees all resources. */ void psplay_delete_key (PSplay self, void* key); enum psplay_order_enum { PSPLAY_PREORDER, PSPLAY_INORDER, PSPLAY_POSTORDER }; /** * Traverse a splay tree * Traversing a tree calls a user supplied action three times * An 'action' must not alter the tree itself but it can indicate aborting the tree traversal and * how the current node is handled by its return value. * @param node pointer to the currently traversed node * @param which state of the traversal: * PSPLAY_PREORDER before visiting the left subtree, * PSPLAY_INORDER after visiting the left subtree and before the right subtree * PSPLAY_POSTORDER finally after visiting the right subtree. * Example: For to traverse the tree in order action would only handle PSPLAY_INORDER. * This action shall return PSPLAY_CONT when the traversal of the tree shall continue. * @param level depth of the node in the tree * @param data user supplied data which is transparently passed around * @return a pointer to a function which indicates how to proceed, there are three special * return values predefined: * PSPLAY_CONT - continue with the traversal * PSPLAY_STOP - stop the traversal * PSPLAY_REMOVE - stops the traversal and removes the current node, calling the delete handler * any other psplay_delete_fn - stops the traversal and removes the current node, calling the returned delete handler with it */ typedef psplay_delete_fn (*psplay_action_fn)(PSplaynode node, const enum psplay_order_enum which, int level, void* data); extern const psplay_delete_fn PSPLAY_CONT; extern const psplay_delete_fn PSPLAY_STOP; extern const psplay_delete_fn PSPLAY_REMOVE; /** * Start a tree traversal * @param self the tree to be traversed * @param node pointer to root node where traversal shall start, use NULL for the whole tree * @param action handler function as defined above * @param level initial value for the level * @param data user supplied data which is transparently passed to the action * @return 0 when the tree traversal got aborted (by anything but PSPLAY_CONT as action handler return) * 1 when the whole tree was traversed successfully */ int psplay_walk (PSplay self, PSplaynode node, psplay_action_fn action, int level, void* data); void psplay_dump (PSplay self, FILE* dest); #endif /* // Local Variables: // mode: C // c-file-style: "gnu" // indent-tabs-mode: nil // End: */