mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1420 lines
40 KiB
1420 lines
40 KiB
/*++
|
|
|
|
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);
|
|
}
|
|
|
|
}
|