windows-nt/Source/XPSP1/NT/base/ntos/rtl/triangle.c
2020-09-26 16:20:57 +08:00

1421 lines
40 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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);
}
}