326 lines
9.9 KiB
C
326 lines
9.9 KiB
C
//
|
||
// Define the two pointer triangle splay links and the associated
|
||
// manipuliation macros and routines. Note that the tri_splay_links should
|
||
// be an opaque type. Routine are provided to traverse and manipulate the
|
||
// structure.
|
||
//
|
||
// The structure of a tri_splay_links record is really
|
||
//
|
||
// typedef struct _TRI_SPLAY_LINKS {
|
||
// ULONG ParSib; // struct _TRI_SPLAY_LINKS *ParSib;
|
||
// ULONG Child; // struct _TRI_SPLAY_LINKS *Child;
|
||
// } TRI_SPLAY_LINKS;
|
||
//
|
||
// However to aid in debugging (and without extra cost) we declare the
|
||
// structure to be a union so we can also reference the links as pointers
|
||
// in the debugger.
|
||
//
|
||
|
||
typedef union _TRI_SPLAY_LINKS {
|
||
struct {
|
||
ULONG ParSib;
|
||
ULONG Child;
|
||
} Refs;
|
||
struct {
|
||
union _TRI_SPLAY_LINKS *ParSibPtr;
|
||
union _TRI_SPLAY_LINKS *ChildPtr;
|
||
} Ptrs;
|
||
} TRI_SPLAY_LINKS;
|
||
typedef TRI_SPLAY_LINKS *PTRI_SPLAY_LINKS;
|
||
|
||
//
|
||
// The macro procedure InitializeSplayLinks takes as input a pointer to
|
||
// splay link and initializes its substructure. All splay link nodes must
|
||
// be initialized before they are used in the different splay routines and
|
||
// macros.
|
||
//
|
||
// VOID
|
||
// TriInitializeSplayLinks (
|
||
// IN PTRI_SPLAY_LINKS Links
|
||
// );
|
||
//
|
||
|
||
#define TriInitializeSplayLinks(Links) { \
|
||
(Links)->Refs.ParSib = MakeIntoParentRef(Links); \
|
||
(Links)->Refs.Child = 0; \
|
||
}
|
||
|
||
//
|
||
// The macro function Parent takes as input a pointer to a splay link in a
|
||
// tree and returns a pointer to the splay link of the parent of the input
|
||
// node. If the input node is the root of the tree the return value is
|
||
// equal to the input value.
|
||
//
|
||
// PTRI_SPLAY_LINKS
|
||
// TriParent (
|
||
// IN PTRI_SPLAY_LINKS Links
|
||
// );
|
||
//
|
||
|
||
#define TriParent(Links) ( \
|
||
(IsParentRef((Links)->Refs.ParSib)) ? \
|
||
MakeIntoPointer((Links)->Refs.ParSib) \
|
||
: \
|
||
MakeIntoPointer(MakeIntoPointer((Links)->Refs.ParSib)->Refs.ParSib) \
|
||
)
|
||
|
||
//
|
||
// The macro function LeftChild takes as input a pointer to a splay link in
|
||
// a tree and returns a pointer to the splay link of the left child of the
|
||
// input node. If the left child does not exist, the return value is NULL.
|
||
//
|
||
// PTRI_SPLAY_LINKS
|
||
// TriLeftChild (
|
||
// IN PTRI_SPLAY_LINKS Links
|
||
// );
|
||
//
|
||
|
||
#define TriLeftChild(Links) ( \
|
||
(IsLeftChildRef((Links)->Refs.Child)) ? \
|
||
MakeIntoPointer((Links)->Refs.Child) \
|
||
: \
|
||
0 \
|
||
)
|
||
|
||
//
|
||
// The macro function RightChild takes as input a pointer to a splay link
|
||
// in a tree and returns a pointer to the splay link of the right child of
|
||
// the input node. If the right child does not exist, the return value is
|
||
// NULL.
|
||
//
|
||
// PTRI_SPLAY_LINKS
|
||
// TriRightChild (
|
||
// IN PTRI_SPLAY_LINKS Links
|
||
// );
|
||
//
|
||
|
||
#define TriRightChild(Links) ( \
|
||
(IsRightChildRef((Links)->Refs.Child)) ? \
|
||
MakeIntoPointer((Links)->Refs.Child) \
|
||
: ( \
|
||
(IsLeftChildRef((Links)->Refs.Child) && \
|
||
IsSiblingRef(MakeIntoPointer((Links)->Refs.Child)->Refs.ParSib)) ? \
|
||
MakeIntoPointer(MakeIntoPointer((Links)->Refs.Child)->Refs.ParSib) \
|
||
: \
|
||
0 \
|
||
) \
|
||
)
|
||
|
||
//
|
||
// The macro function IsRoot takes as input a pointer to a splay link
|
||
// in a tree and returns TRUE if the input node is the root of the tree,
|
||
// otherwise it returns FALSE.
|
||
//
|
||
// BOOLEAN
|
||
// TriIsRoot (
|
||
// IN PTRI_SPLAY_LINKS Links
|
||
// );
|
||
//
|
||
|
||
#define TriIsRoot(Links) ( \
|
||
(IsParentRef((Links)->Refs.ParSib) && MakeIntoPointer((Links)->Refs.ParSib) == (Links)) ? \
|
||
TRUE \
|
||
: \
|
||
FALSE \
|
||
)
|
||
|
||
//
|
||
// The macro function IsLeftChild takes as input a pointer to a splay link
|
||
// in a tree and returns TRUE if the input node is the left child of its
|
||
// parent, otherwise it returns FALSE. Note that if the input link is the
|
||
// root node this function returns FALSE.
|
||
//
|
||
// BOOLEAN
|
||
// TriIsLeftChild (
|
||
// IN PTRI_SPLAY_LINKS Links
|
||
// );
|
||
//
|
||
|
||
#define TriIsLeftChild(Links) ( \
|
||
(TriLeftChild(TriParent(Links)) == (Links)) ? \
|
||
TRUE \
|
||
: \
|
||
FALSE \
|
||
)
|
||
|
||
//
|
||
// The macro function IsRightChild takes as input a pointer to a splay link
|
||
// in a tree and returns TRUE if the input node is the right child of its
|
||
// parent, otherwise it returns FALSE. Note that if the input link is the
|
||
// root node this function returns FALSE.
|
||
//
|
||
// BOOLEAN
|
||
// TriIsRightChild (
|
||
// IN PTRI_SPLAY_LINKS Links
|
||
// );
|
||
//
|
||
|
||
#define TriIsRightChild(Links) ( \
|
||
(TriRightChild(TriParent(Links)) == (Links)) ? \
|
||
TRUE \
|
||
: \
|
||
FALSE \
|
||
)
|
||
|
||
//
|
||
// The macro procedure InsertAsLeftChild takes as input a pointer to a splay
|
||
// link in a tree and a pointer to a node not in a tree. It inserts the
|
||
// second node as the left child of the first node. The first node must not
|
||
// already have a left child, and the second node must not already have a
|
||
// parent.
|
||
//
|
||
// VOID
|
||
// TriInsertAsLeftChild (
|
||
// IN PTRI_SPLAY_LINKS ParentLinks,
|
||
// IN PTRI_SPLAY_LINKS ChildLinks
|
||
// );
|
||
//
|
||
|
||
#define TriInsertAsLeftChild(ParentLinks,ChildLinks) { \
|
||
PTRI_SPLAY_LINKS RightChild; \
|
||
if ((ParentLinks)->Refs.Child == 0) { \
|
||
(ParentLinks)->Refs.Child = MakeIntoLeftChildRef(ChildLinks); \
|
||
(ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
|
||
} else { \
|
||
RightChild = TriRightChild(ParentLinks); \
|
||
(ParentLinks)->Refs.Child = MakeIntoLeftChildRef(ChildLinks); \
|
||
(ChildLinks)->Refs.ParSib = MakeIntoSiblingRef(RightChild); \
|
||
} \
|
||
}
|
||
|
||
//
|
||
// The macro procedure InsertAsRightChild takes as input a pointer to a splay
|
||
// link in a tree and a pointer to a node not in a tree. It inserts the
|
||
// second node as the right child of the first node. The first node must not
|
||
// already have a right child, and the second node must not already have a
|
||
// parent.
|
||
//
|
||
// VOID
|
||
// TriInsertAsRightChild (
|
||
// IN PTRI_SPLAY_LINKS ParentLinks,
|
||
// IN PTRI_SPLAY_LINKS ChildLinks
|
||
// );
|
||
//
|
||
|
||
#define TriInsertAsRightChild(ParentLinks,ChildLinks) { \
|
||
PTRI_SPLAY_LINKS LeftChild; \
|
||
if ((ParentLinks)->Refs.Child == 0) { \
|
||
(ParentLinks)->Refs.Child = MakeIntoRightChildRef(ChildLinks); \
|
||
(ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
|
||
} else { \
|
||
LeftChild = TriLeftChild(ParentLinks); \
|
||
LeftChild->Refs.ParSib = MakeIntoSiblingRef(ChildLinks); \
|
||
(ChildLinks)->Refs.ParSib = MakeIntoParentRef(ParentLinks); \
|
||
} \
|
||
}
|
||
|
||
//
|
||
// The Splay function takes as input a pointer to a splay link in a tree
|
||
// and splays the tree. Its function return value is a pointer to the
|
||
// root of the splayed tree.
|
||
//
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriSplay (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
//
|
||
// The Delete function takes as input a pointer to a splay link in a tree
|
||
// and deletes that node from the tree. Its function return value is a
|
||
// pointer to the root of the tree. If the tree is now empty, the return
|
||
// value is NULL.
|
||
//
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriDelete (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
//
|
||
// The SubtreeSuccessor function takes as input a pointer to a splay link
|
||
// in a tree and returns a pointer to the successor of the input node of
|
||
// the substree rooted at the input node. If there is not a successor, the
|
||
// return value is NULL.
|
||
//
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriSubtreeSuccessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
//
|
||
// The SubtreePredecessor function takes as input a pointer to a splay link
|
||
// in a tree and returns a pointer to the predecessor of the input node of
|
||
// the substree rooted at the input node. If there is not a predecessor,
|
||
// the return value is NULL.
|
||
//
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriSubtreePredecessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
//
|
||
// The RealSuccessor function takes as input a pointer to a splay link
|
||
// in a tree and returns a pointer to the successor of the input node within
|
||
// the entire tree. If there is not a successor, the return value is NULL.
|
||
//
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriRealSuccessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
//
|
||
// The RealPredecessor function takes as input a pointer to a splay link
|
||
// in a tree and returns a pointer to the predecessor of the input node
|
||
// within the entire tree. If there is not a predecessor, the return value
|
||
// is NULL.
|
||
//
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriRealPredecessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
|
||
//
|
||
// The remainder of this module really belong in triangle.c None of
|
||
// the macros or routines are (logically) exported for use by the programmer
|
||
// however they need to appear in this module to allow the earlier macros
|
||
// to function properly.
|
||
//
|
||
// In the splay record (declared earlier) the low order bit of the
|
||
// ParSib field indicates whether the link is to a Parent or a Sibling, and
|
||
// the low order bit of the Child field is used to indicate if the link
|
||
// is to a left child or a right child. The values are:
|
||
//
|
||
// A parent field has the lower bit set to 0
|
||
// A sibling field has the lower bit set to 1
|
||
// A left child field has the lower bit set to 0
|
||
// A right child field has the lower bit set to 1
|
||
//
|
||
// The comments and code in triangle.c use the term "Ref" to indicate a
|
||
// ParSib field or a Child field with the low order bit to indicate its type.
|
||
// A ref cannot be directly used as a pointer. The following macros help
|
||
// in deciding the type of a ref and making refs from pointers. There is
|
||
// also a macro (MakeIntoPointer) that takes a ref and returns a pointer.
|
||
//
|
||
|
||
#define IsParentRef(Ulong) (((((ULONG)Ulong) & 1) == 0) && ((Ulong) != 0) ? TRUE : FALSE)
|
||
#define MakeIntoParentRef(Ulong) (((ULONG)Ulong) & 0xfffffffc)
|
||
|
||
#define IsSiblingRef(Ulong) ((((ULONG)Ulong) & 1) == 1 ? TRUE : FALSE)
|
||
#define MakeIntoSiblingRef(Ulong) (((ULONG)Ulong) | 1)
|
||
|
||
#define IsLeftChildRef(Ulong) (((((ULONG)Ulong) & 1) == 0) && ((Ulong) != 0) ? TRUE : FALSE)
|
||
#define MakeIntoLeftChildRef(Ulong) (((ULONG)Ulong) & 0xfffffffc)
|
||
|
||
#define IsRightChildRef(Ulong) ((((ULONG)Ulong) & 1) == 1 ? TRUE : FALSE)
|
||
#define MakeIntoRightChildRef(Ulong) (((ULONG)Ulong) | 1)
|
||
|
||
#define MakeIntoPointer(Ulong) ((PTRI_SPLAY_LINKS)((Ulong) & 0xfffffffc))
|
||
|
||
|