123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463 |
- /**
- \ingroup lub
- \defgroup lub_bintree bintree
- @{
- \brief This interface provides a facility which enables a client to
- order and access a set of arbitary data in a binary "tree"
-
- Each "tree" is defined by a number of "clientnodes" which are
- ordered according to a client defined "key".
- A "clientkey" is a client specific entity which can be compared
- with a "clientnode" to determine which is the "greatest". In order
- to do this the client needs provide a comparison function for
- comparing a "clientnode" with a "clientkey", and a function to
- convert a "clientnode" into a "clientkey".
- The client is responsible for providing each "clientnode" in a
- tree. This will typically contain some client specific data, but
- will also need to contain a bintree "node" which is used to
- structurally relate each node to one another in the tree. A
- specific "node" may only belong to one tree at a time, but an
- individual "clientnode" may contain multiple of these if necessary.
- \par Implementation
- The implementation of this interface uses a top-down splaying algorithm.
- \par
- "Splay trees", or "self-adjusting search trees" are a simple and
- efficient data structure for storing an ordered set. The data
- structure consists of a binary tree, without parent pointers, and
- no additional fields. It allows searching, insertion, deletion,
- deletemin, deletemax, splitting, joining, and many other
- operations, all with amortized logarithmic performance. Since the
- trees adapt to the sequence of requests, their performance on real
- access patterns is typically even better. Splay trees are
- described in a number of texts and papers [1,2,3,4,5].
- \par
- The code here is adapted from simple top-down splay, at the bottom
- of page 669 of [3]. It can be obtained via anonymous ftp from
- spade.pc.cs.cmu.edu in directory /usr/sleator/public.
- \par
- The chief modification here is that the splay operation works even
- if the item being splayed is not in the tree, and even if the tree
- root of the tree is NULL. So the line:
- \par
- t = splay(i, t);
- \par
- causes it to search for item with key i in the tree rooted at t.
- If it's there, it is splayed to the root. If it isn't there,
- then the node put at the root is the last one before NULL that
- would have been reached in a normal binary search for i. (It's a
- neighbor of i in the tree.) This allows many other operations to
- be easily implemented.
- \par
- [1] "Fundamentals of data structures in C", Horowitz, Sahni,
- and Anderson-Freed, Computer Science Press, pp 542-547.
- \par
- [2] "Data Structures and Their Algorithms", Lewis and Denenberg,
- Harper Collins, 1991, pp 243-251.
- \par
- [3] "Self-adjusting Binary Search Trees" Sleator and Tarjan,
- JACM Volume 32, No 3, July 1985, pp 652-686.
- \par
- [4] "Data Structure and Algorithm Analysis", Mark Weiss,
- Benjamin Cummins, 1992, pp 119-130.
- \par
- [5] "Data Structures, Algorithms, and Performance", Derick Wood,
- Addison-Wesley, 1993, pp 367-375.
- \par
- The splay function is based on one written by Daniel Sleator, which is released
- in the public domain.
-
- \author Graeme McKerrell
- \date Created On : Fri Jan 23 12:50:18 2004
- \version TESTED
- */
- /*---------------------------------------------------------------
- HISTORY
- 7-Dec-2004 Graeme McKerrell
- Updated to use the "lub" prefix
- 27-Feb-2004 Graeme McKerrell
- updated to simplify node initialisation
- 9-Feb-2004 Graeme McKerrell
- updated to make the comparision function compare a "clientnode" and
- "key"
- Updated getkey() function to fill out a provides "key" from a "clientnode"
- 23-Jan-2004 Graeme McKerrell
- Initial version
- --------------------------------------------------------------
- Copyright (C) 2004 3Com Corporation. All Rights Reserved.
- **************************************************************** */
- #ifndef _lub_bintree_h
- #define _lub_bintree_h
- #include <stddef.h>
- /****************************************************************
- * TYPE DEFINITIONS
- **************************************************************** */
- /**
- * This type represents a bintree "node".
- * Typically the client will have a "clientnode" structure which
- * contains it's data. A bintree "node" is made one of the data
- * elements of that structure. When the tree is initialised the
- * client provides the offset into the structure of the
- * "node" which is to be used for that tree.
- */
- typedef struct lub_bintree_node_s lub_bintree_node_t;
- /**
- * CLIENTS MUSTN'T TOUCH THE CONTENTS OF THIS STRUCTURE
- */
- struct lub_bintree_node_s {
- /** internal */ lub_bintree_node_t *left;
- /** internal */ lub_bintree_node_t *right;
- };
- /**
- * This type defines a callback function which will compare two "keys"
- * with each other
- *
- * \param clientnode the client node to compare
- * \param clientkey the key to compare with a node
- *
- * \return
- * <0 if clientnode < clientkey;
- * 0 if clientnode == clientkey;
- * >0 if clientnode > clientkey
- */
- typedef int
- lub_bintree_compare_fn(const void *clientnode, const void *clientkey);
- /**
- * This is used to size the key storage area for an opaque key.
- * If any client requires a greater storage size then this will need to
- * be increased.
- */
- #define lub_bintree_MAX_KEY_STORAGE (200)
- /**
- * This is used to declare an opaque key structure
- * Typically a client would declare their own non-opaque structure
- * which they would fill out appropriately
- */
- typedef struct lub_bintree_key_s lub_bintree_key_t;
- /**
- * CLIENTS MUSTN'T TOUCH THE CONTENTS OF THIS STRUCTURE
- */
- struct lub_bintree_key_s {
- /** internal */ char storage[lub_bintree_MAX_KEY_STORAGE];
- /** internal */ int magic;
- };
- /**
- * This type defines a callback function which will convert a client's "node"
- * into a search "key"
- *
- * \param clientnode the node from which to derive a key
- * \param key a reference to the key to fill out
- *
- * \return
- * A "key" which corresponds the "node" in this view
- */
- typedef void
- lub_bintree_getkey_fn(const void *clientnode, lub_bintree_key_t * key);
- /**
- * This type represents an binary tree instance
- */
- typedef struct lub_bintree_s lub_bintree_t;
- /**
- * CLIENTS MUSTN'T TOUCH THE CONTENTS OF THIS STRUCTURE
- */
- struct lub_bintree_s {
- /** internal */ lub_bintree_node_t *root;
- /** internal */ size_t node_offset;
- /** internal */ lub_bintree_compare_fn *compareFn;
- /** internal */ lub_bintree_getkey_fn *getkeyFn;
- };
- /**
- * This is used to perform iterations of a tree
- */
- typedef struct lub_bintree_iterator_s lub_bintree_iterator_t;
- /**
- * CLIENTS MUSTN'T TOUCH THE CONTENTS OF THIS STRUCTURE
- */
- struct lub_bintree_iterator_s {
- /** internal */ lub_bintree_t *tree;
- /** internal */ lub_bintree_key_t key;
- };
- /****************************************************************
- * BINTREE OPERATIONS
- **************************************************************** */
- /**
- * This operation initialises an instance of a binary tree.
- *
- * \pre none
- *
- * \post The tree is ready to have client nodes inserted.
- */
- extern void lub_bintree_init(
- /**
- * the "tree" instance to initialise
- */
- lub_bintree_t * tree,
- /**
- * the offset of the bintree "node" structure within the
- * "clientnode" structure. This is typically passed
- * using the offsetof() macro.
- */
- size_t node_offset,
- /**
- * a comparison function for comparing a "clientnode"
- * with a "clientkey"
- */
- lub_bintree_compare_fn compareFn,
- /**
- * a function which will fill out a "key" from a clientnode
- */
- lub_bintree_getkey_fn getkeyFn);
- /**
- * This operation is called to initialise a "clientnode" ready for
- * insertion into a tree. This is only required once after the memory
- * for a node has been allocated.
- *
- * \pre none
- *
- * \post The node is ready to be inserted into a tree.
- */
- extern void lub_bintree_node_init(
- /**
- * the bintree node to initialise
- */
- lub_bintree_node_t * node);
- /*****************************************
- * NODE MANIPULATION OPERATIONS
- ***************************************** */
- /**
- * This operation adds a client node to the specified tree.
- *
- * \pre The tree must be initialised
- * \pre The clientnode must be initialised
- *
- * \return
- * 0 if the "clientnode" is added correctly to the tree.
- * If another "clientnode" already exists in the tree with the same key, then
- * -1 is returned, and the tree remains unchanged.
- *
- * \post If the bintree "node" is already part of a tree, then an
- * assert will fire.
- */
- extern int lub_bintree_insert(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree,
- /**
- * a pointer to a client node. NB the tree can find the
- * necessary lub_BintreeNodeT from it's stored offset.
- */
- void *clientnode);
- /**
- * This operation removes a "clientnode" from the specified "tree"
- *
- * \pre The tree must be initialised
- * \pre The clientnode must be initialised
- *
- * \post The "clientnode" will no longer be part of the specified tree, and will be
- * made available for re-insertion
- * \post If the clientnode is not present in the specified tree, then an
- * assert will fire.
- */
- extern void lub_bintree_remove(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree,
- /**
- * the node to remove
- */
- void *clientnode);
- /*****************************************
- * NODE RETRIEVAL OPERATIONS
- ***************************************** */
- /**
- * This operation returns the first "clientnode" present in the specified "tree"
- *
- * \pre The tree must be initialised
- *
- * \return
- * "clientnode" instance or NULL if no nodes are present in this tree.
- */
- extern void *lub_bintree_findfirst(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree);
- /**
- * This operation returns the last "clientnode" present in the specified "tree"
- *
- * \pre The tree must be initialised
- *
- * \return
- * "clientnode" instance or NULL if no nodes are present in this tree.
- */
- extern void *lub_bintree_findlast(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree);
- /**
- * This operation searches the specified "tree" for a "clientnode" which matches the
- * specified "key"
- *
- * \pre The tree must be initialised
- *
- * \return
- * "clientnode" instance or NULL if no node is found.
- */
- extern void *lub_bintree_find(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree,
- /**
- * the "key" to search with
- */
- const void *key);
- /**
- * This operation searches the specified "tree" for a "clientnode" which is
- * the one which logically follows the specified "key"
- *
- * A "clientnode" with the specified "key" doesn't need to be in the tree.
- *
- * \pre The tree must be initialised
- *
- * \return
- * "clientnode" instance or NULL if no node is found.
- */
- extern void *lub_bintree_findnext(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree,
- /**
- * the "key" to search with
- */
- const void *key);
- /**
- * This operation searches the specified "tree" for a "clientnode" which is
- * the one which logically preceeds the specified "key"
- *
- * A "clientnode" with the specified "key" doesn't need to be in the tree.
- *
- * \pre The tree must be initialised
- *
- * \return
- * "clientnode" instance or NULL if no node is found.
- */
- extern void *lub_bintree_findprevious(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree,
- /**
- * the "key" to search with
- */
- const void *key);
- /*****************************************
- * ITERATION OPERATIONS
- ***************************************** */
- /**
- * This operation initialises an iterator. This can then be
- * subsequently used for iterating through a tree. This will work
- * even if the "clientnode" which defined the current iterator has been
- * removed before the next iterator operation.
- *
- * \pre The tree must be initialised
- * \pre The clientnode must be initialised and valid at the time of this call
- *
- * \post The interator instance will be updated to reference the position in the tree for the clientnode.
- */
- extern void lub_bintree_iterator_init(
- /**
- * the iterator instance to initialise
- */
- lub_bintree_iterator_t * iter,
- /**
- * the tree to associate with this iterator
- */
- lub_bintree_t * tree,
- /**
- * the starting point for the iteration
- */
- const void *clientnode);
- /**
- * This operation returns the next "clientnode" in an iteration.
- *
- * \pre The interator instance must have been initialised
- *
- * \return
- * "clientnode" instance or NULL if the iteration has reached the end of the
- * tree.
- *
- * \post The interator instance will be updated to reference the position in the tree for the returned value.
- */
- extern void *lub_bintree_iterator_next(
- /**
- * the iterator instance to invoke this operation upon.
- */
- lub_bintree_iterator_t * iter);
- /**
- * This operation returns the previous "clientnode" in an iteration.
- *
- * \pre The interator instance must have been initialised
- *
- * \return
- * "clientnode" instance or NULL if the iteration has reached the beginning
- * of the tree.
- *
- * \post The interator instance will be updated to reference the position in the tree for the returned value.
- */
- extern void *lub_bintree_iterator_previous(
- /**
- * the iterator instance to invoke this operation upon.
- */
- lub_bintree_iterator_t *
- iter);
- /**
- * This operation dumps the node list of the specified tree to stdout
- *
- * \pre The tree must be initialised
- *
- * \post The structure of the tree will be unaltered.
- */
- extern void lub_bintree_dump(
- /**
- * the "tree" instance to invoke this operation upon
- */
- lub_bintree_t * tree);
- #endif /* _lub_bintree_h */
- /** @} */
|