/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * Copyright by the Board of Trustees of the University of Illinois. * * All rights reserved. * * * * This file is part of HDF. The full HDF copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the files COPYING and Copyright.html. COPYING can be found at the root * * of the source code distribution tree; Copyright.html can be found at * * http://hdfgroup.org/products/hdf4/doc/Copyright.html. If you do not have * * access to either file, you may request a copy from help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* $Id: tbbt.h 6043 2014-01-21 21:09:03Z acheng $ */ /* "tbbt.h" -- Data types/routines for threaded, balanced, binary trees. */ /* Extended from Knuth 6.2.3, Algorithm A */ #ifndef TBBT_H #define TBBT_H #include "H4api_adpt.h" #ifdef lint /* lint always complains but may complain more if... */ # define TBBT_INTERNALS /* TBBT_INTERNALS not always defined */ #endif /* lint */ typedef struct tbbt_node TBBT_NODE; /* Threaded node structure */ struct tbbt_node { VOIDP data; /* Pointer to user data to be associated with node */ VOIDP key; /* Field to sort nodes on */ #ifdef TBBT_INTERNALS # define PARENT 0 # define LEFT 1 # define RIGHT 2 TBBT_NODE *link[3]; /* Pointers to parent, left child, and right child */ # define Parent link[PARENT] # define Lchild link[LEFT] # define Rchild link[RIGHT] # define TBBT_FLAG unsigned long # define TBBT_LEAF unsigned long TBBT_FLAG flags; /* Combination of the following bit fields: */ # define TBBT_HEAVY(s) s /* If the `s' sub-tree is deeper than the other */ # define TBBT_DOUBLE 4 /* If "heavy" sub-tree is two levels deeper */ # define TBBT_INTERN 8 /* If node is internal (has two children) */ # define TBBT_UNBAL ( TBBT_HEAVY(LEFT) | TBBT_HEAVY(RIGHT) ) # define TBBT_FLAGS ( TBBT_UNBAL | TBBT_INTERN | TBBT_DOUBLE ) # define TBBT_CHILD(s) ( TBBT_INTERN | TBBT_HEAVY(s) ) TBBT_LEAF lcnt; /* count of left children */ TBBT_LEAF rcnt; /* count of right children */ # define LeftCnt(node) ( (node)->lcnt ) /* Left descendants */ # define RightCnt(node) ( (node)->rcnt ) /* Left descendants */ # define Cnt(node,s) ( LEFT==(s) ? LeftCnt(node) : RightCnt(node) ) # define HasChild(n,s) ( Cnt(n,s)>0 ) # define Heavy(n,s) ( (s) & (LeftCnt(n)>RightCnt(n) ? LEFT : \ LeftCnt(n)==RightCnt(n) ? 0 : RIGHT)) # define Intern(n) ( LeftCnt(n) && RightCnt(n) ) # define UnBal(n) ( LeftCnt(n)>RightCnt(n) ? LEFT : \ LeftCnt(n)==RightCnt(n) ? 0 : RIGHT) # define Double(n) ( TBBT_DOUBLE & (n)->flags ) # define Other(side) ( LEFT + RIGHT - (side) ) # define Delta(n,s) ( ( Heavy(n,s) ? 1 : -1 ) \ * ( Double(n) ? 2 : UnBal(n) ? 1 : 0 ) ) # define SetFlags(n,s,b,i) ( ( -2<(b) && (b)<2 ? 0 : TBBT_DOUBLE ) \ | ( 0>(b) ? TBBT_HEAVY(s) : (b)>0 ? TBBT_HEAVY(Other(s)) : 0 ) \ | ( (i) ? TBBT_INTERN : 0 ) ) }; /* Pointer to the tbbt node free list */ static TBBT_NODE *tbbt_free_list=NULL; typedef struct tbbt_tree TBBT_TREE; /* Threaded tree structure */ struct tbbt_tree { TBBT_NODE *root; unsigned long count; /* The number of nodes in the tree currently */ uintn fast_compare; /* use a faster in-line compare (with casts) instead of function call */ intn (*compar) (VOIDP k1, VOIDP k2, intn cmparg); intn cmparg; #endif /* TBBT_INTERNALS */ }; /* Define the "fast compare" values */ #define TBBT_FAST_UINT16_COMPARE 1 #define TBBT_FAST_INT32_COMPARE 2 #ifndef TBBT_INTERNALS typedef TBBT_NODE **TBBT_TREE; #endif /* TBBT_INTERNALS */ /* Return maximum of two scalar values (use arguments w/o side effects): */ #define Max(a,b) ( (a) > (b) ? (a) : (b) ) /* These routines are designed to allow use of a general-purpose balanced tree * implimentation. These trees are appropriate for maintaining in memory one * or more lists of items, each list sorted according to key values (key values * must form a "completely ordered set") where no two items in a single list * can have the same key value. The following operations are supported: * Create an empty list * Add an item to a list * Look up an item in a list by key value * Look up the Nth item in a list * Delete an item from a list * Find the first/last/next/previous item in a list * Destroy a list * Each of the above operations requires Order(log(N)) time where N is the * number of items in the list (except for list creation which requires * constant time and list destruction which requires Order(N) time if the user- * supplied free-data-item or free-key-value routines require constant time). * Each of the above operations (except create and destroy) can be performed * on a subtree. * * Each node of a tree has associated with it a generic pointer (void *) which * is set to point to one such "item" and a generic pointer to point to that * item's "key value". The structure of the items and key values is up to the * user to define. The user must specify a method for comparing key values. * This routine takes three arguments, two pointers to key values and a third * integer argument. You can specify a routine that expects pointers to "data * items" rather than key values in which case the pointer to the key value in * each node will be set equal to the pointer to the data item. * * Since the "data item" pointer is the first field of each tree node, these * routines may be used without this "tbbt.h" file. For example, assume "ITM" * is the structre definition for the data items you want to store in lists: * ITM ***tbbtdmake( int (*cmp)(void *,void *,int), int arg ); * ITM **root= NULL; (* How to create an empty tree w/o tbbtdmake() *) * ITM **tbbtdfind( ITM ***tree, void *key, ITM ***pp ); * ITM **tbbtfind( ITM **root, void *key, int (*cmp)(), int arg, ITM ***pp ); * ITM **tbbtdless( ITM ***tree, void *key, ITM ***pp ); * ITM **tbbtless( ITM **root, void *key, int (*cmp)(), int arg, ITM ***pp ); * ITM **tbbtindx( ITM **root, long indx ); * ITM **tbbtdins( ITM ***tree, ITM *item, void *key ); * ITM **tbbtins( ITM ***root, ITM *item, void *key, int (*cmp)(), int arg ); * ITM *tbbtrem( ITM ***root, ITM **node, void **kp ); * ITM **tbbtfirst( ITM **root ), **tbbtlast( ITM **root ); * ITM **tbbtnext( ITM **node ), **tbbtprev( ITM **node ); * ITM ***tbbtdfree( ITM ***tree, void (*df)(ITM *), void (*kf)(void *) ); * void tbbtfree( ITM ***root, void (*df)(ITM *), void (*kf)(void *) ); */ #if defined c_plusplus || defined __cplusplus extern "C" { #endif /* c_plusplus || __cplusplus */ HDFLIBAPI TBBT_TREE *tbbtdmake (intn (*compar) (VOIDP, VOIDP, intn), intn arg, uintn fast_compare); /* Allocates and initializes an empty threaded, balanced, binary tree and * returns a pointer to the control structure for it. You can also create * empty trees without this function as long as you never use tbbtd* routines * (tbbtdfind, tbbtdins, tbbtdfree) on them. * Examples: * int keycmp(); * TBBT_ROOT *root= tbbtdmake( keycmp, (int)keysiz , 0); * or * void *root= tbbtdmake( strcmp, 0 , 0); * or * void *root= tbbtdmake( keycmp, (int)keysiz , TBBT_FAST_UINT16_COMPARE); * or * TBBT_NODE *root= NULL; (* Don't use tbbtd* routines *) * `cmp' is the routine to be used to compare two key values [in tbbtdfind() * and tbbtdins()]. The arguments to `cmp' are the two keys to compare * and `arg': (*cmp)(k1,k2,arg). `cmp' is expected to return 0 if its first * two arguments point to identical key values, -1 (or any integer less than 0) * if k1 points to a key value lower than that pointed to by k2, and 1 (or any * integer greater than 0) otherwise. If `cmp' is NULL, memcmp is used. If * `cmp' is NULL and `arg' is not greater than 0L, `1+strlen(key1)' is used in * place of `arg' to emulate strcmp(): memcmp( k1, k2, 1+strlen(k1) ). You * can use strcmp() directly (as in the second example above) as long as your C * compiler does not assume strcmp() will always be passed exactly 2 arguments * (only newer, ANSI-influenced C compilers are likely to be able to make this * kind of assumption). You can also use a key comparison routine that expects * pointers to data items rather than key values. * The "fast compare" option is for keys of simple numeric types (currently * uint16 and int32) and avoids the function call for faster searches in * some cases. The key comparison routine is still required for some * insertion routines which use it. * * Most of the other routines expect a pointer to a root node of a tree, not * a pointer to the tree's control structure (only tbbtdfind(), tbbtdins(), * and tbbtdfree() expect pointers to control structures). However TBBT_TREE * is just defined as "**TBBT_NODE" (unless you have defined TBBT_INTERNALS so * you have access to the internal structure of the nodes) so * TBBT_TREE *tree1= tbbtdmake( NULL, 0 ); * is equivalent to * TBBT_NODE **tree1= tbbtdmake( NULL, 0 ); * So could be used as: * node= tbbtdfind( tree1, key, NULL ); * node= tbbtfind( *tree1, key, compar, arg, NULL ); * node= tbbtdless( tree1, key, NULL ); * node= tbbtless( *tree1, key, compar, arg, NULL ); * node= tbbtdins( tree1, item, key ); * node= tbbtins( tree1, item, key, compar, arg ); * item= tbbtrem( tree1, tbbtdfind(tree1,key,NULL), NULL ); * item= tbbtrem( tree1, tbbtfind(*tree1,key,compar,arg,NULL), NULL ); * tree1= tbbtdfree( tree1, free, NULL ); (* or whatever *) * while * TBBT_NODE *root= NULL; * would be used like: * node= tbbtfind( root, key ); * node= tbbtins( &root, item, key ); * node= tbbtrem( &root, tbbtfind(root,key), NULL ); * tbbtfree( &root, free, NULL ); (* or whatever *) * Never use tbbtfree() on a tree allocated with tbbtdmake() or on a sub-tree * of ANY tree. Never use tbbtdfree() except on a tbbtdmake()d tree. */ HDFLIBAPI TBBT_NODE *tbbtdfind (TBBT_TREE * tree, VOIDP key, TBBT_NODE ** pp); HDFLIBAPI TBBT_NODE *tbbtfind (TBBT_NODE * root, VOIDP key, intn (*cmp) (VOIDP, VOIDP, intn), intn arg, TBBT_NODE ** pp); HDFLIBAPI TBBT_NODE *tbbtdless (TBBT_TREE * tree, VOIDP key, TBBT_NODE ** pp); HDFLIBAPI TBBT_NODE *tbbtless (TBBT_NODE * root, VOIDP key, intn (*cmp) (VOIDP, VOIDP, intn), intn arg, TBBT_NODE ** pp); /* Locate a node based on the key given. A pointer to the node in the tree * with a key value matching `key' is returned. If no such node exists, NULL * is returned. Whether a node is found or not, if `pp' is not NULL, `*pp' * will be set to point to the parent of the node we are looking for (or that * node that would be the parent if the node is not found). tbbtdfind() is * used on trees created using tbbtdmake() (so that `cmp' and `arg' don't have * to be passed). tbbtfind() can be used on the root or any subtree of a tree * create using tbbtdmake() and is used on any tree (or subtree) created with- * out using tbbtdmake(). tbbtless() & tbbtdless() work exactly like tbbtfind() * and tbbtdfind() except that they find the node with a key which is less than * or equal to the key given to them. */ HDFLIBAPI TBBT_NODE *tbbtindx (TBBT_NODE * root, int32 indx); /* Locate the node that has `indx' nodes with lesser key values. This is like * an array lookup with the first item in the list having index 0. For large * values of `indx', this call is much faster than tbbtfirst() followed by * `indx' tbbtnext()s. Thus `tbbtindx(&root,0L)' is equivalent to (and almost * as fast as) `tbbtfirst(root)'. */ HDFLIBAPI TBBT_NODE *tbbtdins (TBBT_TREE * tree, VOIDP item, VOIDP key); HDFLIBAPI TBBT_NODE *tbbtins (TBBT_NODE ** root, VOIDP item, VOIDP key, intn (*cmp) (VOIDP, VOIDP, intn), intn arg); /* Insert a new node to the tree having a key value of `key' and a data pointer * of `item'. If a node already exists in the tree with key value `key' or if * malloc() fails, NULL is returned (no node is inserted), otherwise a pointer * to the inserted node is returned. `cmp' and `arg' are as for tbbtfind(). */ HDFLIBAPI VOIDP tbbtrem (TBBT_NODE ** root, TBBT_NODE * node, VOIDP *kp); /* Remove the node pointed to by `node' from the tree with root `root'. The * data pointer for the deleted node is returned. If the second argument is * NULL, NULL is returned. If `kp' is not NULL, `*kp' is set to point to the * key value for the deleted node. Examples: * data= tbbtrem( tree, tbbtdfind(tree,key), &kp ); free(data); free(kp); * data= tbbtrem( &root, tbbtfind(root,key,compar,arg), NULL ); * data= tbbtrem( &tree->root, tbbtdfind(tree,key), NULL ); */ HDFLIBAPI TBBT_NODE *tbbtfirst (TBBT_NODE * root); HDFLIBAPI TBBT_NODE *tbbtlast (TBBT_NODE * root); /* Returns a pointer to node from the tree with the lowest(first)/highest(last) * key value. If the tree is empy NULL is returned. Examples: * node= tbbtfirst(*tree); * node= tbbtfirst(root); * node= tbbtlast(tree->root); * node= tbbtlast(node); (* Last node in a sub-tree *) */ HDFLIBAPI TBBT_NODE *tbbtnext (TBBT_NODE * node); HDFLIBAPI TBBT_NODE *tbbtprev (TBBT_NODE * node); /* Returns a pointer the node from the tree with the next highest (previous * lowest) key value relative to the node pointed to by `node'. If `node' * points the last (first) node of the tree, NULL is returned. */ HDFLIBAPI TBBT_TREE *tbbtdfree (TBBT_TREE * tree, VOID(*fd) (VOIDP), VOID(*fk) (VOIDP)); HDFLIBAPI VOID tbbtfree (TBBT_NODE ** root, VOID(*fd) (VOIDP), VOID(*fk) (VOIDP)); /* Frees up an entire tree. `fd' is a pointer to a function that frees/ * destroys data items, and `fk' is the same for key values. * void free(); * tree= tbbtdfree( tree, free, free ); * tbbtfree( &root, free, free ); * is a typical usage, where keys and data are individually malloc()d. If `fk' * is NULL, no action is done for the key values (they were allocated on the * stack, as a part of each data item, or together with one malloc() call, for * example) and likewise for `fd'. tbbtdfree() always returns NULL and * tbbtfree() always sets `root' to be NULL. */ HDFLIBAPI VOID tbbtprint (TBBT_NODE * node); /* Prints out the data in a node */ HDFLIBAPI VOID tbbtdump (TBBT_TREE * tree, intn method); /* Prints an entire tree. The method variable determines which sort of * traversal is used: * -1 : Pre-Order Traversal * 1 : Post-Order Traversal * 0 : In-Order Traversal */ HDFLIBAPI long tbbtcount (TBBT_TREE * tree); /* Terminate the buffers used in the tbbt*() interface */ HDFPUBLIC intn tbbt_shutdown(void); #if defined c_plusplus || defined __cplusplus } #endif /* c_plusplus || __cplusplus */ #endif /* TBBT_H */