Files
PlantAI-dev/tools/pymol-env/include/tbbt.h
T
2026-08-03 18:42:47 +08:00

327 lines
16 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 COPYING file, which can be found at the root of the source code *
* distribution tree, or in https://support.hdfgroup.org/ftp/HDF/releases/. *
* If you do not have access to either file, you may request a copy from *
* help@hdfgroup.org. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* $Id$ */
/* "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 */