1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-26 10:04:02 +03:00

Updates to all of these base level modules.

Trees: Previously, the AVL node type was different than the node type used
       in the BinTree and SplayTree modules.  It requires an additional
       field to maintain AVL balance information.  I merged that field into
       the base type (in ubi_BinTree.h) so that all three use the same
       node type.  On most systems this will have zero effect on the node
       size, due to word alignment.  The change allowed me to remove a
       bigbunch of redundant code, which makes the AVL module smaller and
       cleaner.
Linked Lists:  I combined ubi_StackQueue into ubi_sLinkList.  The interface
       has changed a tiny bit.  I added macros to ubi_dLinkList to round
       it out a bit.

I have verified that the few Samba modules that use these tools (so far)
do not have any problems with the changes.

Chris -)-----
This commit is contained in:
Christopher R. Hertel -
parent 8e4a412dba
commit 599a29401d
10 changed files with 372 additions and 383 deletions

View File

@ -1,7 +1,7 @@
/* ========================================================================== **
* ubi_AVLtree.c
*
* Copyright (C) 1991-1997 by Christopher R. Hertel
* Copyright (C) 1991-1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -32,6 +32,14 @@
* -------------------------------------------------------------------------- **
*
* Log: ubi_AVLtree.c,v
* Revision 4.0 1998/03/10 03:37:09 crh
* Major changes.
* By adding the AVL balance field to the base ubi_btNode structure, I no
* longer need AVL-specific ReplaceNode(), SwapNodes(), and InitNode()
* functions. The Remove() function is also simplified. It's all much
* cleaner.
* This is rev. 4.0. The 3.x series was dropped.
*
* Revision 2.5 1997/12/23 04:00:42 crh
* In this version, all constants & macros defined in the header file have
* the ubi_tr prefix. Also cleaned up anything that gcc complained about
@ -92,10 +100,9 @@
*
* To further complicate matters, only those portions of the base module
* (ubi_BinTree) that were superceeded in the new module had the new names.
* For example, if you were using ubi_AVLtree, the AVL node structure was
* named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using
* SplayTree, the locate function was called "ubi_sptLocate", but the next
* and previous functions remained "ubi_btNext" and "ubi_btPrev".
* For example, if you were using ubi_SplayTree, the locate function was
* called "ubi_sptLocate", but the next and previous functions remained
* "ubi_btNext" and "ubi_btPrev".
*
* This was not too terrible if you were familiar with the modules and knew
* exactly which tree model you wanted to use. If you wanted to be able to
@ -129,8 +136,8 @@
*/
static char ModuleID[] = "ubi_AVLtree\n\
\tRevision: 2.5\n\
\tDate: 1997/12/23 04:00:42\n\
\tRevision: 4.0\n\
\tDate: 1998/03/10 03:37:09\n\
\tAuthor: crh\n";
/* ========================================================================== **
@ -147,7 +154,7 @@ static char ModuleID[] = "ubi_AVLtree\n\
* -------------------------------------------------------------------------- **
*/
static ubi_avlNodePtr L1( ubi_avlNodePtr p )
static ubi_btNodePtr L1( ubi_btNodePtr p )
/* ------------------------------------------------------------------------ **
* Single rotate left.
*
@ -157,7 +164,7 @@ static ubi_avlNodePtr L1( ubi_avlNodePtr p )
* ------------------------------------------------------------------------ **
*/
{
ubi_avlNodePtr tmp;
ubi_btNodePtr tmp;
tmp = p->Link[ubi_trRIGHT];
p->Link[ubi_trRIGHT] = tmp->Link[ubi_trLEFT];
@ -179,7 +186,7 @@ static ubi_avlNodePtr L1( ubi_avlNodePtr p )
return( tmp );
} /* L1 */
static ubi_avlNodePtr R1( ubi_avlNodePtr p )
static ubi_btNodePtr R1( ubi_btNodePtr p )
/* ------------------------------------------------------------------------ **
* Single rotate right.
*
@ -189,7 +196,7 @@ static ubi_avlNodePtr R1( ubi_avlNodePtr p )
* ------------------------------------------------------------------------ **
*/
{
ubi_avlNodePtr tmp;
ubi_btNodePtr tmp;
tmp = p->Link[ubi_trLEFT];
p->Link[ubi_trLEFT] = tmp->Link[ubi_trRIGHT];
@ -211,7 +218,7 @@ static ubi_avlNodePtr R1( ubi_avlNodePtr p )
return( tmp );
} /* R1 */
static ubi_avlNodePtr L2( ubi_avlNodePtr tree )
static ubi_btNodePtr L2( ubi_btNodePtr tree )
/* ------------------------------------------------------------------------ **
* Double rotate left.
*
@ -221,7 +228,7 @@ static ubi_avlNodePtr L2( ubi_avlNodePtr tree )
* ------------------------------------------------------------------------ **
*/
{
ubi_avlNodePtr tmp, newroot;
ubi_btNodePtr tmp, newroot;
tmp = tree->Link[ubi_trRIGHT];
newroot = tmp->Link[ubi_trLEFT];
@ -263,7 +270,7 @@ static ubi_avlNodePtr L2( ubi_avlNodePtr tree )
return( newroot );
} /* L2 */
static ubi_avlNodePtr R2( ubi_avlNodePtr tree )
static ubi_btNodePtr R2( ubi_btNodePtr tree )
/* ------------------------------------------------------------------------ **
* Double rotate right.
*
@ -273,7 +280,7 @@ static ubi_avlNodePtr R2( ubi_avlNodePtr tree )
* ------------------------------------------------------------------------ **
*/
{
ubi_avlNodePtr tmp, newroot;
ubi_btNodePtr tmp, newroot;
tmp = tree->Link[ubi_trLEFT];
newroot = tmp->Link[ubi_trRIGHT];
@ -316,7 +323,7 @@ static ubi_avlNodePtr R2( ubi_avlNodePtr tree )
} /* R2 */
static ubi_avlNodePtr Adjust( ubi_avlNodePtr p, char LorR )
static ubi_btNodePtr Adjust( ubi_btNodePtr p, char LorR )
/* ------------------------------------------------------------------------ **
* Adjust the balance value at node *p. If necessary, rotate the subtree
* rooted at p.
@ -349,9 +356,9 @@ static ubi_avlNodePtr Adjust( ubi_avlNodePtr p, char LorR )
return( p );
} /* Adjust */
static ubi_avlNodePtr Rebalance( ubi_avlNodePtr Root,
ubi_avlNodePtr subtree,
char LorR )
static ubi_btNodePtr Rebalance( ubi_btNodePtr Root,
ubi_btNodePtr subtree,
char LorR )
/* ------------------------------------------------------------------------ **
* Rebalance the tree following an insertion.
*
@ -387,9 +394,9 @@ static ubi_avlNodePtr Rebalance( ubi_avlNodePtr Root,
return( Root );
} /* Rebalance */
static ubi_avlNodePtr Debalance( ubi_avlNodePtr Root,
ubi_avlNodePtr subtree,
char LorR )
static ubi_btNodePtr Debalance( ubi_btNodePtr Root,
ubi_btNodePtr subtree,
char LorR )
/* ------------------------------------------------------------------------ **
* Rebalance the tree following a deletion.
*
@ -428,125 +435,22 @@ static ubi_avlNodePtr Debalance( ubi_avlNodePtr Root,
return( Root );
} /* Debalance */
/* -------------------------------------------------------------------------- **
* The next two functions are used for general tree manipulation. They are
* each slightly different from their ubi_BinTree counterparts.
* -------------------------------------------------------------------------- **
*/
static void ReplaceNode( ubi_avlNodePtr *parent,
ubi_avlNodePtr oldnode,
ubi_avlNodePtr newnode )
/* ------------------------------------------------------------------------ **
* Remove node oldnode from the tree, replacing it with node newnode.
*
* Input:
* parent - A pointer to he parent pointer of the node to be
* replaced. <parent> may point to the Link[] field of
* a parent node, or it may indicate the root pointer at
* the top of the tree.
* oldnode - A pointer to the node that is to be replaced.
* newnode - A pointer to the node that is to be installed in the
* place of <*oldnode>.
*
* Notes: Don't forget to free oldnode.
* The only difference between this function and the ubi_bt
* version is that the node size is sizeof( ubi_avlNode ), not
* sizeof( ubi_btNode ).
* ------------------------------------------------------------------------ **
*/
{
register int i;
register int avlNodeSize = sizeof( ubi_avlNode );
for( i = 0; i < avlNodeSize; i++ )
((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i];
(*parent) = newnode;
if(oldnode->Link[ubi_trLEFT ] )
(oldnode->Link[ubi_trLEFT ])->Link[ubi_trPARENT] = newnode;
if(oldnode->Link[ubi_trRIGHT] )
(oldnode->Link[ubi_trRIGHT])->Link[ubi_trPARENT] = newnode;
} /* ReplaceNode */
static void SwapNodes( ubi_btRootPtr RootPtr,
ubi_avlNodePtr Node1,
ubi_avlNodePtr Node2 )
/* ------------------------------------------------------------------------ **
* This function swaps two nodes in the tree. Node1 will take the place of
* Node2, and Node2 will fill in the space left vacant by Node 1.
*
* Input:
* RootPtr - pointer to the tree header structure for this tree.
* Node1 - \
* > These are the two nodes which are to be swapped.
* Node2 - /
*
* Notes:
* This function does a three step swap, using a dummy node as a place
* holder. This function is used by ubi_avlRemove().
* The only difference between this function and its ubi_bt counterpart
* is that the nodes are ubi_avlNodes, not ubi_btNodes.
* ------------------------------------------------------------------------ **
*/
{
ubi_avlNodePtr *Parent;
ubi_avlNode dummy;
ubi_avlNodePtr dummy_p = &dummy;
if( Node1->Link[ubi_trPARENT] )
Parent = &((Node1->Link[ubi_trPARENT])->Link[(int)(Node1->gender)]);
else
Parent = (ubi_avlNodePtr *)&(RootPtr->root);
ReplaceNode( Parent, Node1, dummy_p );
if( Node2->Link[ubi_trPARENT] )
Parent = &((Node2->Link[ubi_trPARENT])->Link[(int)(Node2->gender)]);
else
Parent = (ubi_avlNodePtr *)&(RootPtr->root);
ReplaceNode( Parent, Node2, Node1 );
if( dummy_p->Link[ubi_trPARENT] )
Parent = &((dummy_p->Link[ubi_trPARENT])->Link[(int)(dummy_p->gender)]);
else
Parent = (ubi_avlNodePtr *)&(RootPtr->root);
ReplaceNode( Parent, dummy_p, Node2 );
} /* SwapNodes */
/* ========================================================================== **
* Public, exported (ie. not static-ly declared) functions...
* -------------------------------------------------------------------------- **
*/
ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr )
/* ------------------------------------------------------------------------ **
* Initialize a tree node.
*
* Input: NodePtr - pointer to a ubi_btNode structure to be
* initialized.
* Output: a pointer to the initialized ubi_avlNode structure (ie. the
* same as the input pointer).
* ------------------------------------------------------------------------ **
*/
{
(void)ubi_btInitNode( (ubi_btNodePtr)NodePtr );
NodePtr->balance = ubi_trEQUAL;
return( NodePtr );
} /* ubi_avlInitNode */
ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
ubi_avlNodePtr NewNode,
ubi_btItemPtr ItemPtr,
ubi_avlNodePtr *OldNode )
ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
ubi_btNodePtr NewNode,
ubi_btItemPtr ItemPtr,
ubi_btNodePtr *OldNode )
/* ------------------------------------------------------------------------ **
* This function uses a non-recursive algorithm to add a new element to
* the tree.
*
* Input: RootPtr - a pointer to the ubi_btRoot structure that indicates
* the root of the tree to which NewNode is to be added.
* NewNode - a pointer to an ubi_avlNode structure that is NOT
* NewNode - a pointer to an ubi_btNode structure that is NOT
* part of any tree.
* ItemPtr - A pointer to the sort key that is stored within
* *NewNode. ItemPtr MUST point to information stored
@ -585,9 +489,10 @@ ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
* ------------------------------------------------------------------------ **
*/
{
ubi_avlNodePtr OtherP;
ubi_btNodePtr OtherP;
if( !(OldNode) ) OldNode = &OtherP;
if( !(OldNode) )
OldNode = &OtherP;
if( ubi_btInsert( RootPtr,
(ubi_btNodePtr)NewNode,
ItemPtr,
@ -598,7 +503,7 @@ ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
else
{
NewNode->balance = ubi_trEQUAL;
RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_avlNodePtr)RootPtr->root,
RootPtr->root = (ubi_btNodePtr)Rebalance( (ubi_btNodePtr)RootPtr->root,
NewNode->Link[ubi_trPARENT],
NewNode->gender );
}
@ -607,8 +512,8 @@ ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
return( ubi_trFALSE ); /* Failure: could not replace an existing node. */
} /* ubi_avlInsert */
ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr,
ubi_avlNodePtr DeadNode )
ubi_btNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr,
ubi_btNodePtr DeadNode )
/* ------------------------------------------------------------------------ **
* This function removes the indicated node from the tree, after which the
* tree is rebalanced.
@ -622,45 +527,15 @@ ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr,
*
* Note: The node MUST be in the tree indicated by RootPtr. If not,
* strange and evil things will happen to your trees.
*
* ------------------------------------------------------------------------ **
*/
{
ubi_btNodePtr p,
*parentp;
/* if the node has both left and right subtrees, then we have to swap
* it with another node.
*/
if( (DeadNode->Link[ubi_trLEFT]) && (DeadNode->Link[ubi_trRIGHT]) )
SwapNodes( RootPtr, DeadNode, ubi_trPrev( DeadNode ) );
/* The parent of the node to be deleted may be another node, or it may be
* the root of the tree. Since we're not sure, it's best just to have
* a pointer to the parent pointer, whatever it is.
*/
if( DeadNode->Link[ubi_trPARENT] )
parentp = (ubi_btNodePtr *)
&((DeadNode->Link[ubi_trPARENT])->Link[(int)(DeadNode->gender)]);
else
parentp = &( RootPtr->root );
/* Now link the parent to the only grand-child. Patch up the gender and
* such, and rebalance.
*/
if( ubi_trEQUAL == DeadNode->balance )
(*parentp) = NULL;
else
{
p = (ubi_btNodePtr)(DeadNode->Link[(int)(DeadNode->balance)]);
p->Link[ubi_trPARENT] = (ubi_btNodePtr)DeadNode->Link[ubi_trPARENT];
p->gender = DeadNode->gender;
(*parentp) = p;
}
RootPtr->root = (ubi_btNodePtr)Debalance( (ubi_avlNodePtr)RootPtr->root,
DeadNode->Link[ubi_trPARENT],
DeadNode->gender );
(RootPtr->count)--;
/* Let the base binary tree module do the removal, then rebalance. */
if( ubi_btRemove( RootPtr, DeadNode ) )
RootPtr->root = Debalance( RootPtr->root,
DeadNode->Link[ubi_trPARENT],
DeadNode->gender );
return( DeadNode );
} /* ubi_avlRemove */

View File

@ -3,7 +3,7 @@
/* ========================================================================== **
* ubi_AVLtree.h
*
* Copyright (C) 1991-1997 by Christopher R. Hertel
* Copyright (C) 1991-1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -35,6 +35,14 @@
*
* -------------------------------------------------------------------------- **
* Log: ubi_AVLtree.h,v
* Revision 4.0 1998/03/10 03:34:45 crh
* Major changes.
* By adding the AVL balance field to the base ubi_btNode structure, I no
* longer need AVL-specific ReplaceNode(), SwapNodes(), and InitNode()
* functions. The Remove() function is also simplified. It's all much
* cleaner.
* This is rev. 4.0. The 3.x series was dropped.
*
* Revision 2.5 1997/12/23 04:00:15 crh
* In this version, all constants & macros defined in the header file have
* the ubi_tr prefix. Also cleaned up anything that gcc complained about
@ -95,10 +103,9 @@
*
* To further complicate matters, only those portions of the base module
* (ubi_BinTree) that were superceeded in the new module had the new names.
* For example, if you were using ubi_AVLtree, the AVL node structure was
* named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using
* SplayTree, the locate function was called "ubi_sptLocate", but the next
* and previous functions remained "ubi_btNext" and "ubi_btPrev".
* For example, if you were using ubi_SplayTree, the locate function was
* called "ubi_sptLocate", but the next and previous functions remained
* "ubi_btNext" and "ubi_btPrev".
*
* This was not too terrible if you were familiar with the modules and knew
* exactly which tree model you wanted to use. If you wanted to be able to
@ -126,70 +133,22 @@
#include "ubi_BinTree.h" /* Base erg binary tree support. */
/* ------------------------------------------------------------------------- **
* AVL Tree Node Structure: This structure defines the basic elements of
* the AVL tree nodes. In general you *SHOULD NOT PLAY WITH THESE
* FIELDS*! But, of course, I have to put the structure into this
* header so that you can use the structure as a building block.
*
* The fields are as follows:
* Link - An array of pointers. These pointers are manipulated by the
* BT and AVL routines, and indicate the left and right child
* nodes, plus the parent node. By keeping track of the parent
* pointer, we avoid the need for recursive routines or hand-
* tooled stacks to keep track of our path back to the root.
* The use of these pointers is subject to change without
* notice.
* gender - For tree rebalancing purposes, it is necessary that each node
* know whether it is the left or right child of its parent, or
* if it is the root. This information is stored in this field.
* balance - This field is also needed for AVL balancing purposes. It
* indicates which subtree of the current node is longer, or if
* the subtrees are, in fact, balanced with respect to each
* other.
* ------------------------------------------------------------------------- **
*/
typedef struct ubi_avlNodeStruct {
struct ubi_avlNodeStruct
*Link[3]; /* Normal Binary Tree Node type. */
char gender; /* The node is either the RIGHT or LEFT child of its */
/* parent, or is the root node. */
char balance; /* In an AVL tree, each node is the root of a subtree */
/* that may be balanced, or be one node longer to the */
/* right or left. This field keeps track of the */
/* balance value of each node. */
} ubi_avlNode;
typedef ubi_avlNode *ubi_avlNodePtr; /* a Pointer to an AVL node */
/* -------------------------------------------------------------------------- **
* Function prototypes.
* -------------------------------------------------------------------------- **
*/
ubi_avlNodePtr ubi_avlInitNode( ubi_avlNodePtr NodePtr );
/* ------------------------------------------------------------------------ **
* Initialize a tree node.
*
* Input: NodePtr - a pointer to a ubi_btNode structure to be
* initialized.
* Output: a pointer to the initialized ubi_avlNode structure (ie. the
* same as the input pointer).
* ------------------------------------------------------------------------ **
*/
ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
ubi_avlNodePtr NewNode,
ubi_btItemPtr ItemPtr,
ubi_avlNodePtr *OldNode );
ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
ubi_btNodePtr NewNode,
ubi_btItemPtr ItemPtr,
ubi_btNodePtr *OldNode );
/* ------------------------------------------------------------------------ **
* This function uses a non-recursive algorithm to add a new element to
* the tree.
*
* Input: RootPtr - a pointer to the ubi_btRoot structure that indicates
* the root of the tree to which NewNode is to be added.
* NewNode - a pointer to an ubi_avlNode structure that is NOT
* NewNode - a pointer to an ubi_btNode structure that is NOT
* part of any tree.
* ItemPtr - A pointer to the sort key that is stored within
* *NewNode. ItemPtr MUST point to information stored
@ -228,8 +187,8 @@ ubi_trBool ubi_avlInsert( ubi_btRootPtr RootPtr,
* ------------------------------------------------------------------------ **
*/
ubi_avlNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr,
ubi_avlNodePtr DeadNode );
ubi_btNodePtr ubi_avlRemove( ubi_btRootPtr RootPtr,
ubi_btNodePtr DeadNode );
/* ------------------------------------------------------------------------ **
* This function removes the indicated node from the tree, after which the
* tree is rebalanced.
@ -273,60 +232,14 @@ int ubi_avlModuleID( int size, char *list[] );
* type by including the appropriate module header.
*/
#undef ubi_trNode
#undef ubi_trNodePtr
#define ubi_trNode ubi_avlNode
#define ubi_trNodePtr ubi_avlNodePtr
#undef ubi_trInitNode
#define ubi_trInitNode( Np ) ubi_avlInitNode( (ubi_avlNodePtr)(Np) )
#undef ubi_trInsert
#define ubi_trInsert( Rp, Nn, Ip, On ) \
ubi_avlInsert( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Nn), \
(ubi_btItemPtr)(Ip), (ubi_avlNodePtr *)(On) )
ubi_avlInsert( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Nn), \
(ubi_btItemPtr)(Ip), (ubi_btNodePtr *)(On) )
#undef ubi_trRemove
#define ubi_trRemove( Rp, Dn ) \
ubi_avlRemove( (ubi_btRootPtr)(Rp), (ubi_avlNodePtr)(Dn) )
#undef ubi_trLocate
#define ubi_trLocate( Rp, Ip, Op ) \
(ubi_avlNodePtr)ubi_btLocate( (ubi_btRootPtr)(Rp), \
(ubi_btItemPtr)(Ip), \
(ubi_trCompOps)(Op) )
#undef ubi_trFind
#define ubi_trFind( Rp, Ip ) \
(ubi_avlNodePtr)ubi_btFind( (ubi_btRootPtr)(Rp), (ubi_btItemPtr)(Ip) )
#undef ubi_trNext
#define ubi_trNext( P ) (ubi_avlNodePtr)ubi_btNext( (ubi_btNodePtr)(P) )
#undef ubi_trPrev
#define ubi_trPrev( P ) (ubi_avlNodePtr)ubi_btPrev( (ubi_btNodePtr)(P) )
#undef ubi_trFirst
#define ubi_trFirst( P ) (ubi_avlNodePtr)ubi_btFirst( (ubi_btNodePtr)(P) )
#undef ubi_trLast
#define ubi_trLast( P ) (ubi_avlNodePtr)ubi_btLast( (ubi_btNodePtr)(P) )
#undef ubi_trFirstOf
#define ubi_trFirstOf( Rp, Ip, P ) \
(ubi_avlNodePtr)ubi_btFirstOf( (ubi_btRootPtr)(Rp), \
(ubi_btItemPtr)(Ip), \
(ubi_btNodePtr)(P) )
#undef ubi_trLastOf
#define ubi_trLastOf( Rp, Ip, P ) \
(ubi_avlNodePtr)ubi_btLastOf( (ubi_btRootPtr)(Rp), \
(ubi_btItemPtr)(Ip), \
(ubi_btNodePtr)(P) )
#undef ubi_trLeafNode
#define ubi_trLeafNode( Nd ) \
(ubi_avlNodePtr)ubi_btLeafNode( (ubi_btNodePtr)(Nd) )
ubi_avlRemove( (ubi_btRootPtr)(Rp), (ubi_btNodePtr)(Dn) )
#undef ubi_trModuleID
#define ubi_trModuleID( s, l ) ubi_avlModuleID( s, l )

View File

@ -1,7 +1,7 @@
/* ========================================================================== **
* ubi_BinTree.c
*
* Copyright (C) 1991-1997 by Christopher R. Hertel
* Copyright (C) 1991-1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -27,6 +27,16 @@
* -------------------------------------------------------------------------- **
*
* Log: ubi_BinTree.c,v
* Revision 4.0 1998/03/10 03:19:22 crh
* Added the AVL field 'balance' to the ubi_btNode structure. This means
* that all BinTree modules now use the same basic node structure, which
* greatly simplifies the AVL module.
* Decided that this was a big enough change to justify a new major revision
* number. 3.0 was an error, so we're at 4.0.
*
* Revision 2.6 1998/01/24 06:27:46 crh
* Added ubi_trCount() macro.
*
* Revision 2.5 1997/12/23 03:56:29 crh
* In this version, all constants & macros defined in the header file have
* the ubi_tr prefix. Also cleaned up anything that gcc complained about
@ -79,10 +89,9 @@
*
* To further complicate matters, only those portions of the base module
* (ubi_BinTree) that were superceeded in the new module had the new names.
* For example, if you were using ubi_AVLtree, the AVL node structure was
* named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using
* SplayTree, the locate function was called "ubi_sptLocate", but the next
* and previous functions remained "ubi_btNext" and "ubi_btPrev".
* For example, if you were using ubi_SplayTree, the locate function was
* called "ubi_sptLocate", but the next and previous functions remained
* "ubi_btNext" and "ubi_btPrev".
*
* This was not too terrible if you were familiar with the modules and knew
* exactly which tree model you wanted to use. If you wanted to be able to
@ -116,8 +125,8 @@
*/
static char ModuleID[] = "ubi_BinTree\n\
\tRevision: 2.5\n\
\tDate: 1997/12/23 03:56:29\n\
\tRevision: 4.0\n\
\tDate: 1998/03/10 03:19:22\n\
\tAuthor: crh\n";
/* ========================================================================== **
@ -209,7 +218,7 @@ static ubi_btNodePtr TreeFind( ubi_btItemPtr findme,
static void ReplaceNode( ubi_btNodePtr *parent,
ubi_btNodePtr oldnode,
ubi_btNodePtr newnode )
/* ------------------------------------------------------------------ *
/* ------------------------------------------------------------------------ **
* Remove node oldnode from the tree, replacing it with node newnode.
*
* Input:
@ -227,7 +236,7 @@ static void ReplaceNode( ubi_btNodePtr *parent,
* that now reads:
* ((unsigned char *)newnode)[i] = ((unsigned char *)oldnode)[i];
* Bleah!
* ------------------------------------------------------------------ *
* ------------------------------------------------------------------------ **
*/
{
register int i;
@ -456,6 +465,7 @@ ubi_btNodePtr ubi_btInitNode( ubi_btNodePtr NodePtr )
NodePtr->Link[ ubi_trPARENT ] = NULL;
NodePtr->Link[ ubi_trRIGHT ] = NULL;
NodePtr->gender = ubi_trEQUAL;
NodePtr->balance = ubi_trEQUAL;
return( NodePtr );
} /* ubi_btInitNode */

View File

@ -3,7 +3,7 @@
/* ========================================================================== **
* ubi_BinTree.h
*
* Copyright (C) 1991-1997 by Christopher R. Hertel
* Copyright (C) 1991-1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -29,6 +29,16 @@
* -------------------------------------------------------------------------- **
*
* Log: ubi_BinTree.h,v
* Revision 4.0 1998/03/10 03:16:04 crh
* Added the AVL field 'balance' to the ubi_btNode structure. This means
* that all BinTree modules now use the same basic node structure, which
* greatly simplifies the AVL module.
* Decided that this was a big enough change to justify a new major revision
* number. 3.0 was an error, so we're at 4.0.
*
* Revision 2.6 1998/01/24 06:27:30 crh
* Added ubi_trCount() macro.
*
* Revision 2.5 1997/12/23 03:59:21 crh
* In this version, all constants & macros defined in the header file have
* the ubi_tr prefix. Also cleaned up anything that gcc complained about
@ -81,10 +91,9 @@
*
* To further complicate matters, only those portions of the base module
* (ubi_BinTree) that were superceeded in the new module had the new names.
* For example, if you were using ubi_AVLtree, the AVL node structure was
* named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using
* SplayTree, the locate function was called "ubi_sptLocate", but the next
* and previous functions remained "ubi_btNext" and "ubi_btPrev".
* For example, if you were using ubi_SplayTree, the locate function was
* called "ubi_sptLocate", but the next and previous functions remained
* "ubi_btNext" and "ubi_btPrev".
*
* This was not too terrible if you were familiar with the modules and knew
* exactly which tree model you wanted to use. If you wanted to be able to
@ -197,6 +206,16 @@ typedef enum {
#define ubi_trOvwt_OK(A) \
((ubi_trOVERWRITE & ((A)->flags))?(ubi_trTRUE):(ubi_trFALSE))
/* -------------------------------------------------------------------------- **
* A quickie for consistency.
* ubi_trCount() - Given a pointer to a tree root, this macro returns the
* number of nodes currently in the tree.
*
* -------------------------------------------------------------------------- **
*/
#define ubi_trCount( R ) (((ubi_trRootPtr)(R))->count)
/* -------------------------------------------------------------------------- **
* Typedefs...
*
@ -211,7 +230,7 @@ typedef enum {
typedef unsigned char ubi_trBool;
typedef void *ubi_btItemPtr; /* A pointer to data within a node. */
typedef void *ubi_btItemPtr; /* A pointer to key data within a node. */
/* ------------------------------------------------------------------------- **
* Binary Tree Node Structure: This structure defines the basic elements of
@ -230,11 +249,16 @@ typedef void *ubi_btItemPtr; /* A pointer to data within a node. */
* gender - a one-byte field indicating whether the node is the RIGHT or
* LEFT child of its parent. If the node is the root of the
* tree, gender will be PARENT.
* balance - only used by the AVL tree module. This field indicates
* the height balance at a given node. See ubi_AVLtree for
* details.
*
* ------------------------------------------------------------------------- **
*/
typedef struct ubi_btNodeStruct {
struct ubi_btNodeStruct *Link[ 3 ];
char gender;
signed char gender;
signed char balance;
} ubi_btNode;
typedef ubi_btNode *ubi_btNodePtr; /* Pointer to an ubi_btNode structure. */
@ -272,8 +296,8 @@ typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr );
/* -------------------------------------------------------------------------- **
* Tree Root Structure: This structure gives us a convenient handle for
* accessing whole AVL trees. The fields are:
* root - A pointer to the root node of the AVL tree.
* accessing whole binary trees. The fields are:
* root - A pointer to the root node of the tree.
* count - A count of the number of nodes stored in the tree.
* cmp - A pointer to the comparison routine to be used when building or
* searching the tree.
@ -294,8 +318,8 @@ typedef void (*ubi_btKillNodeRtn)( ubi_btNodePtr );
typedef struct {
ubi_btNodePtr root; /* A pointer to the root node of the tree */
unsigned long count; /* A count of the number of nodes in the tree */
ubi_btCompFunc cmp; /* A pointer to the tree's comparison function */
unsigned long count; /* A count of the number of nodes in the tree */
unsigned char flags; /* Overwrite Y|N, Duplicate keys Y|N... */
} ubi_btRoot;

View File

@ -1,7 +1,7 @@
/* ========================================================================== **
* ubi_SplayTree.c
*
* Copyright (C) 1993-1995 by Christopher R. Hertel
* Copyright (C) 1993-1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -16,6 +16,8 @@
* Robert Tarjan. Journal of the Association for Computing
* Machinery Vol 32, No. 3, July 1985 pp. 652-686
*
* See also: http://www.cs.cmu.edu/~sleator/
*
* -------------------------------------------------------------------------- **
*
* This library is free software; you can redistribute it and/or
@ -35,6 +37,13 @@
* -------------------------------------------------------------------------- **
*
* Log: ubi_SplayTree.c,v
* Revision 4.0 1998/03/10 03:41:33 crh
* Minor comment changes. The revision number is now 4.0 to match the
* BinTree and AVLtree modules.
*
* Revision 2.7 1998/01/24 06:37:08 crh
* Added a URL for more information.
*
* Revision 2.6 1997/12/23 04:01:12 crh
* In this version, all constants & macros defined in the header file have
* the ubi_tr prefix. Also cleaned up anything that gcc complained about
@ -80,10 +89,9 @@
*
* To further complicate matters, only those portions of the base module
* (ubi_BinTree) that were superceeded in the new module had the new names.
* For example, if you were using ubi_AVLtree, the AVL node structure was
* named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using
* SplayTree, the locate function was called "ubi_sptLocate", but the next
* and previous functions remained "ubi_btNext" and "ubi_btPrev".
* For example, if you were using ubi_SplayTree, the locate function was
* called "ubi_sptLocate", but the next and previous functions remained
* "ubi_btNext" and "ubi_btPrev".
*
* This was not too terrible if you were familiar with the modules and knew
* exactly which tree model you wanted to use. If you wanted to be able to
@ -123,8 +131,8 @@
*/
static char ModuleID[] = "ubi_SplayTree\n\
\tRevision: 2.6\n\
\tDate: 1997/12/23 04:01:12\n\
\tRevision: 4.0\n\
\tDate: 1998/03/10 03:41:33\n\
\tAuthor: crh\n";
@ -466,3 +474,4 @@ int ubi_sptModuleID( int size, char *list[] )
} /* ubi_sptModuleID */
/* ================================ The End ================================= */

View File

@ -3,7 +3,7 @@
/* ========================================================================== **
* ubi_SplayTree.h
*
* Copyright (C) 1993,1995 by Christopher R. Hertel
* Copyright (C) 1993-1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -18,6 +18,8 @@
* Robert Tarjan. Journal of the Association for Computing
* Machinery Vol 32, No. 3, July 1985 pp. 652-686
*
* See also: http://www.cs.cmu.edu/~sleator/
*
* -------------------------------------------------------------------------- **
*
* This library is free software; you can redistribute it and/or
@ -37,6 +39,13 @@
* -------------------------------------------------------------------------- **
*
* Log: ubi_SplayTree.h,v
* Revision 4.0 1998/03/10 03:40:57 crh
* Minor comment changes. The revision number is now 4.0 to match the
* BinTree and AVLtree modules.
*
* Revision 2.7 1998/01/24 06:37:57 crh
* Added a URL for more information.
*
* Revision 2.6 1997/12/23 04:02:20 crh
* In this version, all constants & macros defined in the header file have
* the ubi_tr prefix. Also cleaned up anything that gcc complained about
@ -79,10 +88,9 @@
*
* To further complicate matters, only those portions of the base module
* (ubi_BinTree) that were superceeded in the new module had the new names.
* For example, if you were using ubi_AVLtree, the AVL node structure was
* named "ubi_avlNode", but the root structure was still "ubi_btRoot". Using
* SplayTree, the locate function was called "ubi_sptLocate", but the next
* and previous functions remained "ubi_btNext" and "ubi_btPrev".
* For example, if you were using ubi_SplayTree, the locate function was
* called "ubi_sptLocate", but the next and previous functions remained
* "ubi_btNext" and "ubi_btPrev".
*
* This was not too terrible if you were familiar with the modules and knew
* exactly which tree model you wanted to use. If you wanted to be able to
@ -328,8 +336,3 @@ int ubi_sptModuleID( int size, char *list[] );
/* ================================ The End ================================= */
#endif /* ubi_SplayTree_H */

View File

@ -1,7 +1,7 @@
/* ========================================================================== **
* ubi_dLinkList.c
*
* Copyright (C) 1997 by Christopher R. Hertel
* Copyright (C) 1997, 1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -24,6 +24,13 @@
*
* -------------------------------------------------------------------------- **
*
* Log: ubi_dLinkList.c,v
* Revision 0.5 1998/03/10 02:55:00 crh
* Simplified the code and added macros for stack & queue manipulations.
*
* Revision 0.4 1998/01/03 01:53:56 crh
* Added ubi_dlCount() macro.
*
* Revision 0.3 1997/10/15 03:05:39 crh
* Added some handy type casting to the macros. Added AddHere and RemThis
* macros.
@ -35,11 +42,16 @@
* Revision 0.1 1997/10/07 04:34:07 crh
* Initial Revision.
*
* -------------------------------------------------------------------------- **
* This module is similar to the ubi_sLinkList module, but it is neither a
* descendant type nor an easy drop-in replacement for the latter. One key
* difference is that the ubi_dlRemove() function removes the indicated node,
* while the ubi_slRemove() function (in ubi_sLinkList) removes the node
* *following* the indicated node.
*
* ========================================================================== **
*/
#include "../includes.h"
#include "ubi_dLinkList.h"
/* ========================================================================== **
@ -85,28 +97,17 @@ ubi_dlNodePtr ubi_dlInsert( ubi_dlListPtr ListPtr,
* ------------------------------------------------------------------------ **
*/
{
if( NULL == After )
{
New->Next = ListPtr->Head;
New->Prev = NULL;
if( NULL != ListPtr->Head )
ListPtr->Head->Prev = New;
else
ListPtr->Tail = New;
ListPtr->Head = New;
}
else
{
New->Next = After->Next;
New->Prev = After;
if( NULL != After->Next )
After->Next->Prev = New;
else
ListPtr->Tail = New;
After->Next = New;
}
ubi_dlNodePtr PredNode = After ? After : (ubi_dlNodePtr)ListPtr;
++(ListPtr->count);
New->Next = PredNode->Next;
New->Prev = After;
PredNode->Next = New;
if( New->Next )
New->Next->Prev = New;
else
ListPtr->Tail = New;
(ListPtr->count)++;
return( New );
} /* ubi_dlInsert */
@ -125,7 +126,7 @@ ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old )
* ------------------------------------------------------------------------ **
*/
{
if( NULL != Old )
if( Old )
{
if( Old->Next )
Old->Next->Prev = Old->Prev;
@ -137,11 +138,10 @@ ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old )
else
ListPtr->Head = Old->Next;
--(ListPtr->count);
(ListPtr->count)--;
}
return( Old );
} /* ubi_dlRemove */
/* ================================ The End ================================= */

View File

@ -3,7 +3,7 @@
/* ========================================================================== **
* ubi_dLinkList.h
*
* Copyright (C) 1997 by Christopher R. Hertel
* Copyright (C) 1997, 1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
@ -26,6 +26,13 @@
*
* -------------------------------------------------------------------------- **
*
* Log: ubi_dLinkList.h,v
* Revision 0.5 1998/03/10 02:54:04 crh
* Simplified the code and added macros for stack & queue manipulations.
*
* Revision 0.4 1998/01/03 01:53:44 crh
* Added ubi_dlCount() macro.
*
* Revision 0.3 1997/10/15 03:04:31 crh
* Added some handy type casting to the macros. Added AddHere and RemThis
* macros.
@ -37,6 +44,12 @@
* Revision 0.1 1997/10/07 04:34:38 crh
* Initial Revision.
*
* -------------------------------------------------------------------------- **
* This module is similar to the ubi_sLinkList module, but it is neither a
* descendant type nor an easy drop-in replacement for the latter. One key
* difference is that the ubi_dlRemove() function removes the indicated node,
* while the ubi_slRemove() function (in ubi_sLinkList) removes the node
* *following* the indicated node.
*
* ========================================================================== **
*/
@ -73,46 +86,63 @@ typedef ubi_dlList *ubi_dlListPtr;
/* ========================================================================== **
* Macros...
*
*
* ubi_dlCount - Return the number of entries currently in the list.
*
* ubi_dlAddHead - Add a new node at the head of the list.
* ubi_dlAddNext - Add a node following the given node.
* ubi_dlAddTail - Add a new node at the tail of the list.
* ubi_dlAddHere - Add a node following the given node.
* Note: AddTail evaluates the L parameter twice.
*
* ubi_dlRemHead - Remove the node at the head of the list, if any.
* ubi_dlRemTail - Remove the node at the tail of the list, if any.
* Note: RemHead evaluates the L parameter twice.
* ubi_dlRemThis - Remove the indicated node.
* ubi_dlRemTail - Remove the node at the tail of the list, if any.
* Note: RemTail evaluates the L parameter twice.
*
* ubi_dlFirst - Return a pointer to the first node in the list, if any.
* ubi_dlLast - Return a pointer to the last node in the list, if any.
* ubi_dlNext - Given a node, return a pointer to the next node.
* ubi_dlPrev - Given a node, return a pointer to the previous node.
*
* ubi_dlPush - Add a node at the head of the list (synonym of AddHead).
* ubi_dlPop - Remove a node at the head of the list (synonym of RemHead).
* ubi_dlEnqueue - Add a node at the tail of the list (sysnonym of AddTail).
* ubi_dlDequeue - Remove a node at the head of the list (synonym of RemHead).
*
* Note that all of these provide type casting of the parameters. The
* Add and Rem macros are nothing more than nice front-ends to the
* Insert and Remove operations.
*
* Also note that there the First, Next and Last macros do no parameter
* checking!
*
*/
#define ubi_dlCount( L ) (((ubi_dlListPtr)(L))->count)
#define ubi_dlAddHead( L, N ) \
ubi_dlInsert( (ubi_dlListPtr)(L), (ubi_dlNodePtr)(N), NULL )
#define ubi_dlAddNext( L, N, A ) \
ubi_dlInsert( (ubi_dlListPtr)(L), \
(ubi_dlNodePtr)(N), \
(ubi_dlNodePtr)(A) )
#define ubi_dlAddTail( L, N ) \
ubi_dlInsert( (ubi_dlListPtr)(L), \
(ubi_dlNodePtr)(N), \
(((ubi_dlListPtr)(L))->Tail) )
#define ubi_dlAddHere( L, N, P ) \
ubi_dlInsert( (ubi_dlListPtr)(L), \
(ubi_dlNodePtr)(N), \
(ubi_dlNodePtr)(P) )
#define ubi_dlRemHead( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \
(((ubi_dlListPtr)(L))->Head) )
#define ubi_dlRemTail( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \
(((ubi_dlListPtr)(L))->Tail) )
#define ubi_dlRemThis( L, N ) ubi_dlRemove( (ubi_dlListPtr)(L), \
(ubi_dlNodePtr)(N) )
#define ubi_dlRemTail( L ) ubi_dlRemove( (ubi_dlListPtr)(L), \
(((ubi_dlListPtr)(L))->Tail) )
#define ubi_dlFirst( L ) (((ubi_dlListPtr)(L))->Head)
#define ubi_dlLast( L ) (((ubi_dlListPtr)(L))->Tail)
@ -121,6 +151,10 @@ typedef ubi_dlList *ubi_dlListPtr;
#define ubi_dlPrev( N ) (((ubi_dlNodePtr)(N))->Prev)
#define ubi_dlPush ubi_dlAddHead
#define ubi_dlPop ubi_dlRemHead
#define ubi_dlEnqueue ubi_dlAddTail
#define ubi_dlDequeue ubi_dlRemHead
/* ========================================================================== **
* Function prototypes...
@ -173,6 +207,5 @@ ubi_dlNodePtr ubi_dlRemove( ubi_dlListPtr ListPtr, ubi_dlNodePtr Old );
* ------------------------------------------------------------------------ **
*/
/* ================================ The End ================================= */
#endif /* ubi_dLinkList_H */

View File

@ -1,11 +1,11 @@
/* ========================================================================== **
* ubi_sLinkList.c
*
* Copyright (C) 1997 by Christopher R. Hertel
* Copyright (C) 1997, 1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
* This module implements a really simple singly-linked list.
* This module implements a simple singly-linked list.
* -------------------------------------------------------------------------- **
*
* This library is free software; you can redistribute it and/or
@ -24,6 +24,14 @@
*
* -------------------------------------------------------------------------- **
*
* Log: ubi_sLinkList.c,v
* Revision 0.4 1998/03/10 02:23:20 crh
* Combined ubi_StackQueue and ubi_sLinkList into one module. Redesigned
* the functions and macros. Not a complete rewrite but close to it.
*
* Revision 0.3 1998/01/03 01:59:52 crh
* Added ubi_slCount() macro.
*
* Revision 0.2 1997/10/21 03:35:18 crh
* Added parameter <After> in function Insert(). Made necessary changes
* to macro AddHead() and added macro AddHere().
@ -31,6 +39,36 @@
* Revision 0.1 1997/10/16 02:53:45 crh
* Initial Revision.
*
* -------------------------------------------------------------------------- **
* This module implements a singly-linked list which may also be used as a
* queue or a stack. For a queue, entries are added at the tail and removed
* from the head of the list. For a stack, the entries are entered and
* removed from the head of the list. A traversal of the list will always
* start at the head of the list and proceed toward the tail. This is all
* mind-numbingly simple, but I'm surprised by the number of programs out
* there which re-implement this a dozen or so times.
*
* Notes: When the list header is initialized, the Tail pointer is set to
* point to the Head pointer. This simplifies things a great deal,
* except that you can't initialize a stack or queue by simply
* zeroing it out. One sure way to initialize the header is to call
* ubi_slInit(). Another option would be something like this:
*
* static ubi_slList MyList = { NULL, (ubi_slNodePtr)&MyList, 0 };
*
* See ubi_slInit() and the ubi_slList structure for more info.
*
* + Also, note that this module is similar to the ubi_dLinkList
* module. There are three key differences:
* - This is a singly-linked list, the other is a doubly-linked
* list.
* - In this module, if the list is empty, the tail pointer will
* point back to the head of the list as described above. This
* is not done in ubi_dLinkList.
* - The ubi_slRemove() function, by necessity, removed the 'next'
* node. In ubi_dLinkList, the ubi_dlRemove() function removes
* the 'current' node.
*
* ========================================================================== **
*/
@ -54,6 +92,7 @@ ubi_slListPtr ubi_slInitList( ubi_slListPtr ListPtr )
*/
{
ListPtr->Head = NULL;
ListPtr->Tail = (ubi_slNodePtr)ListPtr;
ListPtr->count = 0;
return( ListPtr );
} /* ubi_slInitList */
@ -62,7 +101,7 @@ ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr,
ubi_slNodePtr New,
ubi_slNodePtr After )
/* ------------------------------------------------------------------------ **
* Insert a new node at the head of the list.
* Add a node to the list.
*
* Input: ListPtr - A pointer to the list into which the node is to
* be inserted.
@ -77,36 +116,43 @@ ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr,
* ------------------------------------------------------------------------ **
*/
{
ubi_slNodePtr *PredPtr;
PredPtr = ( NULL == After ) ? &(ListPtr->Head) : &(After->Next);
New->Next = *PredPtr;
*PredPtr = New;
++(ListPtr->count);
After = After ? After : (ubi_slNodePtr)ListPtr;
New->Next = After->Next;
After->Next = New;
if( !(New->Next) )
ListPtr->Tail = New;
(ListPtr->count)++;
return( New );
} /* ubi_slInsert */
ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr )
ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr, ubi_slNodePtr After )
/* ------------------------------------------------------------------------ **
* Remove a node from the head of the list.
* Remove the node followng <After>. If <After> is NULL, remove from the
* head of the list.
*
* Input: ListPtr - A pointer to the list from which the node is to be
* removed.
* After - Pointer to the node preceeding the node to be
* removed.
*
* Output: A pointer to the node that was removed.
* Output: A pointer to the node that was removed, or NULL if the list is
* empty.
*
* ------------------------------------------------------------------------ **
*/
{
ubi_slNodePtr Old = ListPtr->Head;
ubi_slNodePtr DelNode;
if( NULL != Old )
After = After ? After : (ubi_slNodePtr)ListPtr;
DelNode = After->Next;
if( DelNode )
{
ListPtr->Head = Old->Next;
--(ListPtr->count);
if( !(DelNode->Next) )
ListPtr->Tail = After;
After->Next = DelNode->Next;
(ListPtr->count)--;
}
return( Old );
return( DelNode );
} /* ubi_slRemove */
/* ================================ The End ================================= */

View File

@ -3,11 +3,11 @@
/* ========================================================================== **
* ubi_sLinkList.h
*
* Copyright (C) 1997 by Christopher R. Hertel
* Copyright (C) 1997, 1998 by Christopher R. Hertel
*
* Email: crh@ubiqx.mn.org
* -------------------------------------------------------------------------- **
* This module implements a really simple singly-linked list.
* This module implements a simple singly-linked list.
* -------------------------------------------------------------------------- **
*
* This library is free software; you can redistribute it and/or
@ -26,6 +26,14 @@
*
* -------------------------------------------------------------------------- **
*
* Log: ubi_sLinkList.h,v
* Revision 0.4 1998/03/10 02:22:39 crh
* Combined ubi_StackQueue and ubi_sLinkList into one module. Redesigned
* the functions and macros. Not a complete rewrite but close to it.
*
* Revision 0.3 1998/01/03 02:00:02 crh
* Added ubi_slCount() macro.
*
* Revision 0.2 1997/10/21 03:36:14 crh
* Added parameter <After> in function Insert(). Made necessary changes
* to macro AddHead() and added macro AddHere().
@ -33,6 +41,36 @@
* Revision 0.1 1997/10/16 02:54:08 crh
* Initial Revision.
*
* -------------------------------------------------------------------------- **
* This module implements a singly-linked list which may also be used as a
* queue or a stack. For a queue, entries are added at the tail and removed
* from the head of the list. For a stack, the entries are entered and
* removed from the head of the list. A traversal of the list will always
* start at the head of the list and proceed toward the tail. This is all
* mind-numbingly simple, but I'm surprised by the number of programs out
* there which re-implement this a dozen or so times.
*
* Note: When the list header is initialized, the Tail pointer is set to
* point to the Head pointer. This simplifies things a great deal,
* except that you can't initialize a stack or queue by simply
* zeroing it out. One sure way to initialize the header is to call
* ubi_slInit(). Another option would be something like this:
*
* static ubi_slList MyList = { NULL, (ubi_slNodePtr)&MyList, 0 };
*
* See ubi_slInit() and the ubi_slList structure for more info.
*
* + Also, note that this module is similar to the ubi_dLinkList
* module. There are three key differences:
* - This is a singly-linked list, the other is a doubly-linked
* list.
* - In this module, if the list is empty, the tail pointer will
* point back to the head of the list as described above. This
* is not done in ubi_dLinkList.
* - The ubi_slRemove() function, by necessity, removed the 'next'
* node. In ubi_dLinkList, the ubi_dlRemove() function removes
* the 'current' node.
*
* ========================================================================== **
*/
@ -59,6 +97,7 @@ typedef ubi_slNode *ubi_slNodePtr;
typedef struct
{
ubi_slNodePtr Head;
ubi_slNodePtr Tail;
unsigned long count;
} ubi_slList;
@ -67,31 +106,64 @@ typedef ubi_slList *ubi_slListPtr;
/* ========================================================================== **
* Macros...
*
* ubi_slCount - Returns the current number of entries in the list.
*
* ubi_slAddHead - Add a new node at the head of the list.
* ubi_slAddNext - Add a new node following the indicated node.
* ubi_slAddTail - Add a new node to the tail of the list.
* Note: AddTail evaluates the L parameter twice.
*
* ubi_slRemHead - Remove the node at the head of the list, if any.
* ubi_slRemNext - Remove the node following the given node.
*
* ubi_slFirst - Return a pointer to the first node in the list, if any.
* ubi_slNext - Given a node, return a pointer to the next node.
* ubi_slLast - Return a pointer to the last node in the list, if any.
*
* ubi_slPush - Add a node at the head of the list (synonym of AddHead).
* ubi_slPop - Remove a node at the head of the list (synonym of RemHead).
* ubi_slEnqueue - Add a node at the tail of the list (sysnonym of AddTail).
* ubi_slDequeue - Remove a node at the head of the list (synonym of RemHead).
*
* Note that all of these provide type casting of the parameters. The
* Add and Rem macros are nothing more than nice front-ends to the
* Insert and Remove operations.
* Insert and Remove functions.
*
* Also note that there the First, Next and Last macros do no parameter
* checking!
*
*/
#define ubi_slCount( L ) (((ubi_slListPtr)(L))->count)
#define ubi_slAddHead( L, N ) \
ubi_slInsert( (ubi_slListPtr)(L), (ubi_slNodePtr)(N), NULL )
#define ubi_slAddHere( L, N, P ) \
#define ubi_slAddNext( L, N, A ) \
ubi_slInsert( (ubi_slListPtr)(L), \
(ubi_slNodePtr)(N), \
(ubi_slNodePtr)(P) )
(ubi_slNodePtr)(A) )
#define ubi_slRemHead( L ) ubi_slRemove( (ubi_slListPtr)(L) )
#define ubi_slAddTail( L, N ) \
ubi_slInsert( (ubi_slListPtr)(L), \
(ubi_slNodePtr)(N), \
((ubi_slListPtr)(L))->Tail )
#define ubi_slRemHead( L ) ubi_slRemove( (ubi_slListPtr)(L), NULL )
#define ubi_slRemNext( L, N ) \
ubi_slRemove( (ubi_slListPtr)(L), (ubi_slNodePtr)(N) )
#define ubi_slFirst( L ) (((ubi_slListPtr)(L))->Head)
#define ubi_slNext( N ) (((ubi_slNodePtr)(N))->Next)
#define ubi_slLast( L ) (((ubi_slListPtr)(L))->Tail)
#define ubi_slPush ubi_slAddHead
#define ubi_slPop ubi_slRemHead
#define ubi_slEnqueue ubi_slAddTail
#define ubi_slDequeue ubi_slRemHead
/* ========================================================================== **
* Function prototypes...
@ -114,7 +186,7 @@ ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr,
ubi_slNodePtr New,
ubi_slNodePtr After );
/* ------------------------------------------------------------------------ **
* Insert a new node at the head of the list.
* Add a node to the list.
*
* Input: ListPtr - A pointer to the list into which the node is to
* be inserted.
@ -129,14 +201,18 @@ ubi_slNodePtr ubi_slInsert( ubi_slListPtr ListPtr,
* ------------------------------------------------------------------------ **
*/
ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr );
ubi_slNodePtr ubi_slRemove( ubi_slListPtr ListPtr, ubi_slNodePtr After );
/* ------------------------------------------------------------------------ **
* Remove a node from the head of the list.
* Remove the node followng <After>. If <After> is NULL, remove from the
* head of the list.
*
* Input: ListPtr - A pointer to the list from which the node is to be
* removed.
* After - Pointer to the node preceeding the node to be
* removed.
*
* Output: A pointer to the node that was removed.
* Output: A pointer to the node that was removed, or NULL if the list is
* empty.
*
* ------------------------------------------------------------------------ **
*/