1421 lines
40 KiB
C
1421 lines
40 KiB
C
/*++
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
Triangle.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the general splay utilities for a two link
|
||
triangular splay structure.
|
||
|
||
Author:
|
||
|
||
Gary Kimura [GaryKi] 28-May-1989
|
||
|
||
Environment:
|
||
|
||
Pure utility routine
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include <nt.h>
|
||
#include "triangle.h"
|
||
|
||
|
||
//
|
||
// There are three type of swap macros. The first two (are really the same)
|
||
// are used to swap pointer and ulongs. The last macro is used to swap refs
|
||
// but it does not swap the ref type flags.
|
||
//
|
||
|
||
#define SwapPointers(Ptr1, Ptr2) { \
|
||
PVOID _SWAP_POINTER_TEMP; \
|
||
_SWAP_POINTER_TEMP = (PVOID)(Ptr1); \
|
||
(Ptr1) = (Ptr2); \
|
||
(Ptr2) = _SWAP_POINTER_TEMP; \
|
||
}
|
||
|
||
#define SwapUlongs(Ptr1, Ptr2) { \
|
||
ULONG _SWAP_POINTER_TEMP; \
|
||
_SWAP_POINTER_TEMP = (ULONG)(Ptr1); \
|
||
(Ptr1) = (Ptr2); \
|
||
(Ptr2) = _SWAP_POINTER_TEMP; \
|
||
}
|
||
|
||
#define SwapRefsButKeepFlags(Ref1, Ref2) { \
|
||
ULONG _SWAP_ULONG_TEMP; \
|
||
_SWAP_ULONG_TEMP = (ULONG)(Ref1); \
|
||
(Ref1) = ((Ref2) & 0xfffffffc) | ((Ref1) & 0x00000003); \
|
||
(Ref2) = (_SWAP_ULONG_TEMP & 0xfffffffc) | ((Ref2) & 0x00000003); \
|
||
}
|
||
|
||
//
|
||
// The macro SetRefViaPointer takes a pointer to a ref and checks to see if
|
||
// it is a valid pointer. If it is a valid pointer it copies in the ref
|
||
// a ulong, but does not overwrite the ref flags already in the ref.
|
||
//
|
||
|
||
#define SetRefViaPointer(Ref, Ulong) { \
|
||
if (Ref != NULL) { \
|
||
(*(Ref)) = (((ULONG)(Ulong)) & 0xfffffffc) | ((ULONG)(*(Ref)) & 0x00000003); \
|
||
} \
|
||
}
|
||
|
||
|
||
//
|
||
// The following five procedures are local to triangle.c and are used to
|
||
// help manipluate the splay links. The first two procedures take a pointer
|
||
// to a splay link and returns the address of the ref that points back to the
|
||
// input link, via either the parent or child. They return NULL if there is
|
||
// not a back pointer. The result of these two procedures is often used in
|
||
// the code with the SetRefViaPointer macro. The third procedure is used
|
||
// to swap the position to two splay links in the tree (i.e., the links swap
|
||
// position, but everyone else stays stationary). This is a general procedure
|
||
// that can will swap any two nodes, irregardless of their relative positions
|
||
// in the tree. The last two procedures do a single rotation about a
|
||
// tree node. They either rotate left or rotate right and assume that the
|
||
// appropriate child exists (i.e., for rotate left a right child exists and
|
||
// for rotate right a left child exists).
|
||
//
|
||
|
||
PULONG
|
||
TriAddressOfBackRefViaParent (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
PULONG
|
||
TriAddressOfBackRefViaChild (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
VOID
|
||
TriSwapSplayLinks (
|
||
IN PTRI_SPLAY_LINKS Link1,
|
||
IN PTRI_SPLAY_LINKS Link2
|
||
);
|
||
|
||
VOID
|
||
TriRotateRight (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
VOID
|
||
TriRotateLeft (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
);
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriSplay (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This 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.
|
||
|
||
Arguments:
|
||
|
||
Links - Supplies the pointer to a splay link in a tree
|
||
|
||
Return Values:
|
||
|
||
PRTI_SPLAY_LINKS - Returns a pointer to the root of the splayed tree
|
||
|
||
--*/
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Parent;
|
||
PTRI_SPLAY_LINKS GrandParent;
|
||
|
||
//
|
||
// While Links is not the root we test and rotate until it is the root.
|
||
//
|
||
|
||
while (!TriIsRoot(Links)) {
|
||
|
||
//
|
||
// Get Parent and then check if we don't have a grandparent.
|
||
//
|
||
|
||
Parent = TriParent(Links);
|
||
|
||
if (TriIsRoot(Parent)) {
|
||
|
||
//
|
||
// No grandparent so check for single rotation
|
||
//
|
||
|
||
if (TriIsLeftChild(Links)) {
|
||
|
||
//
|
||
// do the following single rotation
|
||
//
|
||
// Parent Links
|
||
// / ==> \
|
||
// Links Parent
|
||
//
|
||
|
||
TriRotateRight(Parent);
|
||
|
||
} else { // TriIsRightChild(Links)
|
||
|
||
//
|
||
// do the following single rotation
|
||
//
|
||
//
|
||
// Parent Links
|
||
// \ ==> /
|
||
// Links Parent
|
||
//
|
||
|
||
TriRotateLeft(Parent);
|
||
|
||
}
|
||
|
||
} else { // !TriIsRoot(Parent)
|
||
|
||
//
|
||
// Get grandparent and check for the four double rotation
|
||
// cases
|
||
//
|
||
|
||
GrandParent = TriParent(Parent);
|
||
|
||
if (TriIsLeftChild(Links)) {
|
||
|
||
if (TriIsLeftChild(Parent)) {
|
||
|
||
//
|
||
// do the following double rotation
|
||
//
|
||
// GP L
|
||
// / \
|
||
// P ==> P
|
||
// / \
|
||
// L GP
|
||
//
|
||
|
||
TriRotateRight(GrandParent);
|
||
TriRotateRight(Parent);
|
||
|
||
} else { // TriIsRightChild(Parent)
|
||
|
||
//
|
||
// do the following double rotation
|
||
//
|
||
// GP L
|
||
// \ / \
|
||
// P ==> GP P
|
||
// /
|
||
// L
|
||
//
|
||
|
||
TriRotateRight(Parent);
|
||
TriRotateLeft(GrandParent);
|
||
|
||
}
|
||
|
||
} else { // TriIsRightChild(Links);
|
||
|
||
if (TriIsLeftChild(Parent)) {
|
||
|
||
//
|
||
// do the following double rotation
|
||
//
|
||
// GP L
|
||
// / / \
|
||
// P ==> P GP
|
||
// \
|
||
// L
|
||
//
|
||
|
||
TriRotateLeft(Parent);
|
||
TriRotateRight(GrandParent);
|
||
|
||
} else { // TriIsRightChild(Parent)
|
||
|
||
//
|
||
// do the following double rotation
|
||
//
|
||
// GP L
|
||
// \ /
|
||
// P ==> P
|
||
// \ /
|
||
// L GP
|
||
//
|
||
|
||
TriRotateLeft(GrandParent);
|
||
TriRotateLeft(Parent);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
return Links;
|
||
|
||
}
|
||
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriDelete (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This 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 the tree. If the tree is now empty, the return
|
||
value is NULL.
|
||
|
||
Arguments:
|
||
|
||
Links - Supplies the pointer to a splay link in a tree
|
||
|
||
Return Values:
|
||
|
||
PRTI_SPLAY_LINKS - Returns a pointer to the root of the splayed tree
|
||
|
||
--*/
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Predecessor;
|
||
PTRI_SPLAY_LINKS Parent;
|
||
PTRI_SPLAY_LINKS Child;
|
||
|
||
PULONG ParentChildRef;
|
||
|
||
//
|
||
// First check to see if Links as two children. If it does then swap
|
||
// Links with its subtree predecessor. Now we are guaranteed that Links
|
||
// has at most one child.
|
||
//
|
||
|
||
if ((TriLeftChild(Links) != NULL) && (TriRightChild(Links) != NULL)) {
|
||
|
||
//
|
||
// get the predecessor, and swap their position in the tree
|
||
//
|
||
|
||
Predecessor = TriSubtreePredecessor(Links);
|
||
TriSwapSplayLinks(Predecessor, Links);
|
||
|
||
}
|
||
|
||
//
|
||
// If Links has no children then delete links by checking if it is
|
||
// already the root or has a parent. If it is the root then the
|
||
// tree is now empty, otherwise set the appropriate parent's child
|
||
// pointer, and possibly sibling, and splay the parent.
|
||
//
|
||
|
||
if ((TriLeftChild(Links) == NULL) && (TriRightChild(Links) == NULL)) {
|
||
|
||
//
|
||
// Links has no children, if it is the root then return NULL
|
||
//
|
||
|
||
if (TriIsRoot(Links)) {
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
//
|
||
// Links has no children, check to see if links is an only child
|
||
//
|
||
|
||
Parent = TriParent(Links);
|
||
if (MakeIntoPointer(Parent->Refs.Child) == Links &&
|
||
MakeIntoPointer(Links->Refs.ParSib) == Parent) {
|
||
|
||
//
|
||
// Links has no children and is an only child. So simply make
|
||
// our parent have no children and splay our parent.
|
||
//
|
||
// Parent Parent
|
||
// | ==>
|
||
// Links
|
||
//
|
||
|
||
Parent->Refs.Child = 0;
|
||
return TriSplay(Parent);
|
||
|
||
} else if (TriIsLeftChild(Links)) {
|
||
|
||
//
|
||
// Links has no children and has a right sibling. So make the
|
||
// parent's child Ref be the right sibling, splay the parent.
|
||
//
|
||
// Parent Parent
|
||
// / \ ==> \
|
||
// Links Sibling Sibling
|
||
//
|
||
|
||
Parent->Refs.Child = MakeIntoRightChildRef(Links->Refs.ParSib);
|
||
return TriSplay(Parent);
|
||
|
||
} else { // TriIsRightChild(Links)
|
||
|
||
//
|
||
// Links has no children and has a left sibling. So make link's
|
||
// back via its parent into a parent ref of link's parent, and
|
||
// splay the parent.
|
||
//
|
||
// Parent Parent
|
||
// / \ /
|
||
// Sibling Links ==> Sibling
|
||
//
|
||
|
||
ParentChildRef = TriAddressOfBackRefViaParent(Links);
|
||
*ParentChildRef = MakeIntoParentRef(Parent);
|
||
return TriSplay(Parent);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//
|
||
// otherwise Links has one child. If it is the root then make the child
|
||
// the new root, otherwise link together the child and parent, and splay
|
||
// the parent. But first remember who our child is.
|
||
//
|
||
|
||
if (TriLeftChild(Links) != NULL) {
|
||
Child = TriLeftChild(Links);
|
||
} else {
|
||
Child = TriRightChild(Links);
|
||
}
|
||
|
||
//
|
||
// If links is the root then we make the child the root and return the
|
||
// child.
|
||
//
|
||
|
||
if (TriIsRoot(Links)) {
|
||
Child->Refs.ParSib = MakeIntoParentRef(Child);
|
||
return Child;
|
||
}
|
||
|
||
//
|
||
// Links is not the root, so set links's back ref via its parent to be
|
||
// links's child and the set the child's ParSib to be link's ParSib, and
|
||
// splay the parent. This will handle the case where link is an only
|
||
// or has a sibling on either side.
|
||
//
|
||
|
||
Parent = TriParent(Links);
|
||
ParentChildRef = TriAddressOfBackRefViaParent(Links);
|
||
SetRefViaPointer(ParentChildRef, Child);
|
||
Child->Refs.ParSib = Links->Refs.ParSib;
|
||
|
||
return TriSplay(Parent);
|
||
|
||
}
|
||
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriSubtreeSuccessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This 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 subtree rooted at the input node. If there is not a successor, the
|
||
return value is NULL.
|
||
|
||
Arguments:
|
||
|
||
Links - Supplies the pointer to a splay link in a tree
|
||
|
||
Return Values:
|
||
|
||
PRTI_SPLAY_LINKS - Returns a pointer to the successor in the subtree
|
||
|
||
--*/
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Ptr;
|
||
|
||
//
|
||
// check to see if there is a right subtree to the input link
|
||
// if there is then the subtree successor is the left most node in
|
||
// the right subtree. That is find and return P in the following diagram
|
||
//
|
||
// Links
|
||
// \
|
||
// .
|
||
// .
|
||
// .
|
||
// /
|
||
// P
|
||
// \
|
||
//
|
||
|
||
if ((Ptr = TriRightChild(Links)) != NULL) {
|
||
|
||
while (TriLeftChild(Ptr) != NULL) {
|
||
Ptr = TriLeftChild(Ptr);
|
||
}
|
||
|
||
return Ptr;
|
||
|
||
}
|
||
|
||
//
|
||
// Otherwise we do not have a subtree successor so we simply return NULL
|
||
//
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriSubtreePredecessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This 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 subtree rooted at the input node. If there is not a predecessor,
|
||
the return value is NULL.
|
||
|
||
Arguments:
|
||
|
||
Links - Supplies the pointer to a splay link in a tree
|
||
|
||
Return Values:
|
||
|
||
PRTI_SPLAY_LINKS - Returns a pointer to the predecessor in the subtree
|
||
|
||
--*/
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Ptr;
|
||
|
||
//
|
||
// check to see if there is a left subtree to the input link
|
||
// if there is then the subtree predecessor is the right most node in
|
||
// the left subtree. That is find and return P in the following diagram
|
||
//
|
||
// Links
|
||
// /
|
||
// .
|
||
// .
|
||
// .
|
||
// P
|
||
// /
|
||
//
|
||
|
||
if ((Ptr = TriLeftChild(Links)) != NULL) {
|
||
|
||
while (TriRightChild(Ptr) != NULL) {
|
||
Ptr = TriRightChild(Ptr);
|
||
}
|
||
|
||
return Ptr;
|
||
|
||
}
|
||
|
||
//
|
||
// Otherwise we do not have a subtree predecessor so we simply return NULL
|
||
//
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriRealSuccessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This RealSuccess 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 tire. If there is not a successor, the return value is NULL.
|
||
|
||
Arguments:
|
||
|
||
Links - Supplies the pointer to a splay link in a tree
|
||
|
||
Return Values:
|
||
|
||
PRTI_SPLAY_LINKS - Returns a pointer to the successor in the entire tree
|
||
|
||
--*/
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Ptr;
|
||
|
||
//
|
||
// first check to see if there is a right subtree to the input link
|
||
// if there is then the real successor is the left most node in
|
||
// the right subtree. That is find and return P in the following diagram
|
||
//
|
||
// Links
|
||
// \
|
||
// .
|
||
// .
|
||
// .
|
||
// /
|
||
// P
|
||
// \
|
||
//
|
||
|
||
if ((Ptr = TriRightChild(Links)) != NULL) {
|
||
|
||
while (TriLeftChild(Ptr) != NULL) {
|
||
Ptr = TriLeftChild(Ptr);
|
||
}
|
||
|
||
return Ptr;
|
||
|
||
}
|
||
|
||
//
|
||
// we do not have a right child so check to see if have a parent and if
|
||
// so find the first ancestor that we are a left decendent of. That
|
||
// is find and return P in the following diagram
|
||
//
|
||
// P
|
||
// /
|
||
// .
|
||
// .
|
||
// .
|
||
// Links
|
||
//
|
||
|
||
Ptr = Links;
|
||
while (!TriIsLeftChild(Ptr) && !TriIsRoot(Ptr)) { // (TriIsRightChild(Ptr)) {
|
||
Ptr = TriParent(Ptr);
|
||
}
|
||
|
||
if (TriIsLeftChild(Ptr)) {
|
||
return TriParent(Ptr);
|
||
}
|
||
|
||
//
|
||
// Otherwise we do not have a real successor so we simply return NULL
|
||
//
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
|
||
PTRI_SPLAY_LINKS
|
||
TriRealPredecessor (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This 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.
|
||
|
||
Arguments:
|
||
|
||
Links - Supplies the pointer to a splay link in a tree
|
||
|
||
Return Values:
|
||
|
||
PRTI_SPLAY_LINKS - Returns a pointer to the predecessor in the entire tree
|
||
|
||
--*/
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Ptr;
|
||
|
||
//
|
||
// first check to see if there is a left subtree to the input link
|
||
// if there is then the real predecessor is the right most node in
|
||
// the left subtree. That is find and return P in the following diagram
|
||
//
|
||
// Links
|
||
// /
|
||
// .
|
||
// .
|
||
// .
|
||
// P
|
||
// /
|
||
//
|
||
|
||
if ((Ptr = TriLeftChild(Links)) != NULL) {
|
||
|
||
while (TriRightChild(Ptr) != NULL) {
|
||
Ptr = TriRightChild(Ptr);
|
||
}
|
||
|
||
return Ptr;
|
||
|
||
}
|
||
|
||
//
|
||
// we do not have a left child so check to see if have a parent and if
|
||
// so find the first ancestor that we are a right decendent of. That
|
||
// is find and return P in the following diagram
|
||
//
|
||
// P
|
||
// \
|
||
// .
|
||
// .
|
||
// .
|
||
// Links
|
||
//
|
||
|
||
Ptr = Links;
|
||
while (TriIsLeftChild(Ptr)) {
|
||
Ptr = TriParent(Ptr);
|
||
}
|
||
|
||
if (!TriIsLeftChild(Ptr) && !TriIsRoot(Ptr)) { // (TriIsRightChild(Ptr)) {
|
||
return TriParent(Ptr);
|
||
}
|
||
|
||
//
|
||
// Otherwise we do not have a real predecessor so we simply return NULL
|
||
//
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
|
||
PULONG
|
||
TriAddressOfBackRefViaParent (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Ptr;
|
||
|
||
//
|
||
// If Links is the root then we do not have a back pointer via our parent
|
||
// so return NULL
|
||
//
|
||
|
||
if (TriIsRoot(Links)) {
|
||
|
||
return NULL;
|
||
|
||
}
|
||
|
||
//
|
||
// We are not the root so find our parent and if our parent directly points
|
||
// to us we return the address of our parent's reference to us. Otherwise
|
||
// (we must be a right child with a sibling) so return the address of
|
||
// our sibling's ParSib reference to us.
|
||
//
|
||
|
||
Ptr = TriParent(Links);
|
||
if (MakeIntoPointer(Ptr->Refs.Child) == Links) {
|
||
return &(Ptr->Refs.Child);
|
||
} else {
|
||
return &(MakeIntoPointer(Ptr->Refs.Child)->Refs.ParSib);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
PULONG
|
||
TriAddressOfBackRefViaChild (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
{
|
||
PTRI_SPLAY_LINKS Ptr;
|
||
|
||
//
|
||
// Make Ptr be the same reference as found in our child field.
|
||
//
|
||
|
||
Ptr = MakeIntoPointer(Links->Refs.Child);
|
||
|
||
//
|
||
// If our child pointer is null then we don't have a back pointer
|
||
// via our child so return NULL.
|
||
//
|
||
|
||
if (Ptr == NULL) {
|
||
return NULL;
|
||
|
||
//
|
||
// if our child directly reference's us (then we only have one child)
|
||
// return the address of the ParSib of our only child.
|
||
//
|
||
|
||
} else if (MakeIntoPointer(Ptr->Refs.ParSib) == Links) {
|
||
return &(Ptr->Refs.ParSib);
|
||
|
||
//
|
||
// otherwise we have two children so return the address of the ParSib
|
||
// of the second child.
|
||
//
|
||
|
||
} else {
|
||
return &(MakeIntoPointer(Ptr->Refs.ParSib)->Refs.ParSib);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
TriSwapSplayLinks (
|
||
IN PTRI_SPLAY_LINKS Link1,
|
||
IN PTRI_SPLAY_LINKS Link2
|
||
)
|
||
|
||
{
|
||
PULONG Parent1ChildRef;
|
||
PULONG Parent2ChildRef;
|
||
|
||
PULONG Child1ParSibRef;
|
||
PULONG Child2ParSibRef;
|
||
|
||
//
|
||
// We have the following situation
|
||
//
|
||
//
|
||
// Parent1 Parent2
|
||
// | |
|
||
// | |
|
||
// Link1 Link2
|
||
// / \ / \
|
||
// / \ / \
|
||
// LC1 RC1 LC2 RC2
|
||
//
|
||
// where one of the links can possibly be the root and one of the links
|
||
// can possibly be a direct child of the other, or can be connected
|
||
// via their sibling pointers. Without loss of generality we'll make
|
||
// link2 be the possible and root and link1 be the possible child, or
|
||
// link2 have a parsib pointer to link1
|
||
//
|
||
|
||
if ((TriIsRoot(Link1)) ||
|
||
(TriParent(Link2) == Link1) ||
|
||
(MakeIntoPointer(Link1->Refs.ParSib) == Link2)) {
|
||
|
||
SwapPointers(Link1, Link2);
|
||
|
||
}
|
||
|
||
//
|
||
// The cases we need to handle are
|
||
//
|
||
// 1. Link1 is not a child of link2, link2 is not the root, and they are not siblings
|
||
// 2. Link1 is not a child of link2, link2 is not the root, and they are siblings
|
||
//
|
||
// 3. Link1 is not a child of link2, link2 is the root
|
||
//
|
||
// 4. Link1 is an only child of link2, and link2 is not the root
|
||
// 5. Link1 is an only child of link2, and link2 is the root
|
||
//
|
||
// 6. Link1 is a left child of link2 (has a sibling), and link2 is not the root
|
||
// 7. Link1 is a left child of link2 (has a sibling), and link2 is the root
|
||
//
|
||
// 8. Link1 is a right child of link2 (has a sibling), and link2 is not the root
|
||
// 9. Link1 is a right child of link2 (has a sibling), and link2 is the root
|
||
//
|
||
// Each case will be handled separately
|
||
//
|
||
|
||
if (TriParent(Link1) != Link2) {
|
||
|
||
if (!TriIsRoot(Link2)) {
|
||
|
||
if (MakeIntoPointer(Link2->Refs.ParSib) != Link1) {
|
||
|
||
//
|
||
// Case 1 - Link1 is not a child of link2,
|
||
// Link2 is not the root, and
|
||
// they are not siblings
|
||
//
|
||
|
||
Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
|
||
Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
|
||
SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
|
||
SwapUlongs(Link1->Refs.ParSib, Link2->Refs.ParSib);
|
||
SetRefViaPointer(Parent1ChildRef, Link2);
|
||
SetRefViaPointer(Parent2ChildRef, Link1);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SetRefViaPointer(Child2ParSibRef, Link1);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Case 2 - Link1 is not a child of link2,
|
||
// Link2 is not the root, and
|
||
// they are siblings
|
||
//
|
||
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
|
||
Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
|
||
SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SetRefViaPointer(Child2ParSibRef, Link1);
|
||
*Parent2ChildRef = MakeIntoLeftChildRef(Link1);
|
||
Link2->Refs.ParSib = Link1->Refs.ParSib;
|
||
Link1->Refs.ParSib = MakeIntoSiblingRef(Link2);
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Case 3 - Link1 is not a child of link2, and
|
||
// Link2 is the root
|
||
//
|
||
|
||
Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
|
||
SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
|
||
Link2->Refs.ParSib = Link1->Refs.ParSib;
|
||
Link1->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SetRefViaPointer(Child2ParSibRef, Link1);
|
||
SetRefViaPointer(Parent1ChildRef, Link2);
|
||
|
||
}
|
||
|
||
} else { // TriParent(Link1) == Link2
|
||
|
||
if (MakeIntoPointer(Link2->Refs.Child) == Link1 &&
|
||
MakeIntoPointer(Link1->Refs.ParSib) == Link2) { // Link1 is an only child
|
||
|
||
if (!TriIsRoot(Link2)) {
|
||
|
||
//
|
||
// Case 4 - Link1 is an only child of link2, and
|
||
// Link2 is not the root
|
||
//
|
||
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SetRefViaPointer(Parent2ChildRef, Link1);
|
||
Link1->Refs.ParSib = Link2->Refs.ParSib;
|
||
Link2->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
SwapRefsButKeepFlags(Link1->Refs.Child, Link2->Refs.Child);
|
||
SetRefViaPointer(&Link1->Refs.Child, Link2);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Case 5 - Link1 is an only child of link2, and
|
||
// Link2 is the root
|
||
//
|
||
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
Link1->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
Link2->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
SwapRefsButKeepFlags(Link1->Refs.Child, Link2->Refs.Child);
|
||
SetRefViaPointer(&Link1->Refs.Child, Link2);
|
||
|
||
}
|
||
|
||
} else if (TriIsLeftChild(Link1)) { // and link1 has a sibling
|
||
|
||
if (!TriIsRoot(Link2)) {
|
||
|
||
//
|
||
// Case 6 - Link1 is a left child of link2 (has a sibling), and
|
||
// Link2 is not the root
|
||
//
|
||
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
|
||
Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SetRefViaPointer(Parent2ChildRef, Link1);
|
||
SetRefViaPointer(Child2ParSibRef, Link1);
|
||
Link2->Refs.Child = Link1->Refs.Child;
|
||
Link1->Refs.Child = MakeIntoLeftChildRef(Link2);
|
||
SwapUlongs(Link1->Refs.ParSib, Link2->Refs.ParSib);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Case 7 - Link1 is a left child of link2 (has a sibling), and
|
||
// Link2 is the root
|
||
//
|
||
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
Child2ParSibRef = TriAddressOfBackRefViaChild(Link2);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SetRefViaPointer(Child2ParSibRef, Link1);
|
||
Link2->Refs.Child = Link1->Refs.Child;
|
||
Link1->Refs.Child = MakeIntoLeftChildRef(Link2);
|
||
Link2->Refs.ParSib = Link1->Refs.ParSib;
|
||
Link1->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
|
||
}
|
||
|
||
} else { // TriIsRightChild(Link1) and Link1 has a sibling
|
||
|
||
if (!TriIsRoot(Link2)) {
|
||
|
||
//
|
||
// Case 8 - Link1 is a right child of link2 (has a sibling), and
|
||
// Link2 is not the root
|
||
//
|
||
|
||
Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
Parent2ChildRef = TriAddressOfBackRefViaParent(Link2);
|
||
SetRefViaPointer(Parent1ChildRef, Link2);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SetRefViaPointer(Parent2ChildRef, Link1);
|
||
SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
|
||
Link1->Refs.ParSib = Link2->Refs.ParSib;
|
||
Link2->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
|
||
} else {
|
||
|
||
//
|
||
// Case 9 - Link1 is a right child of link2 (has a sibling), and
|
||
// Link2 is the root
|
||
//
|
||
|
||
Parent1ChildRef = TriAddressOfBackRefViaParent(Link1);
|
||
Child1ParSibRef = TriAddressOfBackRefViaChild(Link1);
|
||
SetRefViaPointer(Parent1ChildRef, Link2);
|
||
SetRefViaPointer(Child1ParSibRef, Link2);
|
||
SwapUlongs(Link1->Refs.Child, Link2->Refs.Child);
|
||
Link1->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
Link1->Refs.ParSib = MakeIntoParentRef(Link1);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
TriRotateRight (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
{
|
||
BOOLEAN IsRoot;
|
||
PULONG ParentChildRef;
|
||
ULONG SavedParSibRef;
|
||
PTRI_SPLAY_LINKS LeftChild;
|
||
PTRI_SPLAY_LINKS a,b,c;
|
||
|
||
//
|
||
// We perform the following rotation
|
||
//
|
||
// -Links- -LeftChild-
|
||
// / \ / \
|
||
// LeftChild c ==> a Links
|
||
// / \ / \
|
||
// a b b c
|
||
//
|
||
// where Links is a possible root and a,b, and c are all optional.
|
||
// We will consider each combination of optional children individually
|
||
// and handle the case of the root when we set T's parsib pointer and
|
||
// the backpointer to T.
|
||
//
|
||
|
||
//
|
||
// First remember if we are the root and if not also remember our
|
||
// back ref via our parent.
|
||
//
|
||
|
||
if (TriIsRoot(Links)) {
|
||
IsRoot = TRUE;
|
||
} else {
|
||
IsRoot = FALSE;
|
||
ParentChildRef = TriAddressOfBackRefViaParent(Links);
|
||
SavedParSibRef = Links->Refs.ParSib;
|
||
}
|
||
|
||
//
|
||
// Now we set LeftChild, a, b, and c, and then later check for the
|
||
// different combinations. In the diagrams only those links that
|
||
// need to change are shown in the after part.
|
||
//
|
||
|
||
LeftChild = TriLeftChild(Links);
|
||
a = TriLeftChild(LeftChild);
|
||
b = TriRightChild(LeftChild);
|
||
c = TriRightChild(Links);
|
||
|
||
if ((a != NULL) && (b != NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / \ ==> \
|
||
// LeftChild c a ----- Links
|
||
// / \ /
|
||
// a b b - c
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoSiblingRef(Links);
|
||
b->Refs.ParSib = MakeIntoSiblingRef(c);
|
||
Links->Refs.Child = MakeIntoLeftChildRef(b);
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
|
||
} else if ((a != NULL) && (b != NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / ==> \
|
||
// LeftChild a ----- Links
|
||
// / \ /
|
||
// a b b --
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoSiblingRef(Links);
|
||
b->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.Child = MakeIntoLeftChildRef(b);
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
|
||
} else if ((a != NULL) && (b == NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / \ ==> \
|
||
// LeftChild c a ----- Links
|
||
// / /
|
||
// a c
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoSiblingRef(Links);
|
||
Links->Refs.Child = MakeIntoRightChildRef(c);
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
|
||
} else if ((a != NULL) && (b == NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / ==> \
|
||
// LeftChild a ----- Links
|
||
// / /
|
||
// a
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoSiblingRef(Links);
|
||
Links->Refs.Child = 0L;
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
|
||
} else if ((a == NULL) && (b != NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / \ ==> / \
|
||
// LeftChild c Links
|
||
// \ /
|
||
// b b - c
|
||
//
|
||
|
||
b->Refs.ParSib = MakeIntoSiblingRef(c);
|
||
Links->Refs.Child = MakeIntoLeftChildRef(b);
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
|
||
|
||
} else if ((a == NULL) && (b != NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / ==> / \
|
||
// LeftChild Links
|
||
// \ /
|
||
// b b -
|
||
//
|
||
|
||
b->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.Child = MakeIntoLeftChildRef(b);
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
|
||
|
||
} else if ((a == NULL) && (b == NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / \ ==> / \
|
||
// LeftChild c Links
|
||
// /
|
||
// c
|
||
//
|
||
|
||
Links->Refs.Child = MakeIntoRightChildRef(c);
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
|
||
|
||
} else if ((a == NULL) && (b == NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links LeftChild
|
||
// / ==> / \
|
||
// LeftChild Links
|
||
// /
|
||
//
|
||
|
||
Links->Refs.Child = 0L;
|
||
Links->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
LeftChild->Refs.Child = MakeIntoRightChildRef(Links);
|
||
|
||
}
|
||
|
||
if (IsRoot) {
|
||
LeftChild->Refs.ParSib = MakeIntoParentRef(LeftChild);
|
||
} else {
|
||
LeftChild->Refs.ParSib = SavedParSibRef;
|
||
SetRefViaPointer(ParentChildRef, LeftChild);
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
TriRotateLeft (
|
||
IN PTRI_SPLAY_LINKS Links
|
||
)
|
||
|
||
{
|
||
BOOLEAN IsRoot;
|
||
PULONG ParentChildRef;
|
||
ULONG SavedParSibRef;
|
||
PTRI_SPLAY_LINKS RightChild;
|
||
PTRI_SPLAY_LINKS a,b,c;
|
||
|
||
//
|
||
// We perform the following rotation
|
||
//
|
||
// -Links- -RightChild-
|
||
// / \ / \
|
||
// a RightChild ==> Links c
|
||
// / \ / \
|
||
// b c a b
|
||
//
|
||
// where Links is a possible root and a,b, and c are all optional.
|
||
// We will consider each combination of optional children individually
|
||
// and handle the case of the root when we set T's parsib pointer and
|
||
// the backpointer to T.
|
||
//
|
||
|
||
//
|
||
// First remember if we are the root and if not also remember our
|
||
// back ref via our parent.
|
||
//
|
||
|
||
if (TriIsRoot(Links)) {
|
||
IsRoot = TRUE;
|
||
} else {
|
||
IsRoot = FALSE;
|
||
ParentChildRef = TriAddressOfBackRefViaParent(Links);
|
||
SavedParSibRef = Links->Refs.ParSib;
|
||
}
|
||
|
||
//
|
||
// Now we set RightChild, a, b, and c, and then later check for the
|
||
// different combinations. In the diagrams only those links that
|
||
// need to change are shown in the after part.
|
||
//
|
||
|
||
RightChild = TriRightChild(Links);
|
||
a = TriLeftChild(Links);
|
||
b = TriLeftChild(RightChild);
|
||
c = TriRightChild(RightChild);
|
||
|
||
if ((a != NULL) && (b != NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// / \ /
|
||
// a RightChild ==> Links ----- c
|
||
// / \ \
|
||
// b c a - b
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoSiblingRef(b);
|
||
b->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.ParSib = MakeIntoSiblingRef(c);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
} else if ((a != NULL) && (b != NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// / \ /
|
||
// a RightChild ==> Links -----
|
||
// / \
|
||
// b a - b
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoSiblingRef(b);
|
||
b->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.ParSib = MakeIntoParentRef(RightChild);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
} else if ((a != NULL) && (b == NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// / \ /
|
||
// a RightChild ==> Links ----- c
|
||
// \
|
||
// c a -
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.ParSib = MakeIntoSiblingRef(c);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
} else if ((a != NULL) && (b == NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// / \ /
|
||
// a RightChild ==> Links -----
|
||
//
|
||
// a -
|
||
//
|
||
|
||
a->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.ParSib = MakeIntoParentRef(RightChild);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
} else if ((a == NULL) && (b != NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// \ /
|
||
// RightChild ==> Links ----- c
|
||
// / \ / \
|
||
// b c b
|
||
//
|
||
|
||
b->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.Child = MakeIntoRightChildRef(b);
|
||
Links->Refs.ParSib = MakeIntoSiblingRef(c);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
} else if ((a == NULL) && (b != NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// \ /
|
||
// RightChild ==> Links -----
|
||
// / / \
|
||
// b b
|
||
//
|
||
|
||
b->Refs.ParSib = MakeIntoParentRef(Links);
|
||
Links->Refs.Child = MakeIntoRightChildRef(b);
|
||
Links->Refs.ParSib = MakeIntoParentRef(RightChild);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
} else if ((a == NULL) && (b == NULL) && (c != NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// \ /
|
||
// RightChild ==> Links ----- c
|
||
// \ /
|
||
// c
|
||
//
|
||
|
||
Links->Refs.Child = 0L;
|
||
Links->Refs.ParSib = MakeIntoSiblingRef(c);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
} else if ((a == NULL) && (b == NULL) && (c == NULL)) {
|
||
|
||
//
|
||
// Handle the following case
|
||
//
|
||
// Links RightChild
|
||
// \ /
|
||
// RightChild ==> Links -----
|
||
// /
|
||
//
|
||
//
|
||
|
||
Links->Refs.Child = 0L;
|
||
Links->Refs.ParSib = MakeIntoParentRef(RightChild);
|
||
RightChild->Refs.Child = MakeIntoLeftChildRef(Links);
|
||
|
||
}
|
||
|
||
if (IsRoot) {
|
||
RightChild->Refs.ParSib = MakeIntoParentRef(RightChild);
|
||
} else {
|
||
RightChild->Refs.ParSib = SavedParSibRef;
|
||
SetRefViaPointer(ParentChildRef, RightChild);
|
||
}
|
||
|
||
}
|