288 lines
8.8 KiB
C
288 lines
8.8 KiB
C
/*
|
|
psplay.h - probabilistic splay tree
|
|
|
|
Copyright (C)
|
|
2004, 2005, 2006, Christian Thaeter <chth@gmx.net>
|
|
Copyright (C) Lumiera.org
|
|
2007, 2008, Christian Thaeter <ct@pipapo.org>
|
|
|
|
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.
|
|
*/
|
|
|
|
|
|
/** @file psplay.h
|
|
** Probabilistic splay tree.
|
|
** A splay trees is self-optimising (in contrast to self-balancing) datastructure.
|
|
** We introduce here a probabilistic bottom up approach which reduces the splay costs.
|
|
** Without affecting the performance. The randomisation 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.
|
|
*/
|
|
|
|
|
|
#ifndef LIB_PSPLAY_H
|
|
#define LIB_PSPLAY_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
/**
|
|
* 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 del;
|
|
|
|
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 del);
|
|
|
|
|
|
/**
|
|
* 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 del);
|
|
|
|
|
|
/**
|
|
* 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);
|
|
|
|
|
|
/**
|
|
* Initialise a splay tree node
|
|
* The user has to place this nodes within his datastructure and must
|
|
* Initialise them before using them.
|
|
* @param self pointer to the node to be initialised
|
|
* @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 optimised 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 /*LIB_PSPLAY_H*/
|