|
|
/* --------------------------------------------------------------------
Microsoft OS/2 LAN Manager Copyright(c) Microsoft Corp., 1990-1999
RPC - Written by Dov Harel
This file contains the implementation for splay tree self adjusting binary trees -------------------------------------------------------------------- */
#pragma warning ( disable : 4514 )
#include "dict.hxx"
// Handy macros used to define common tree operations.
// Dummy is a member of the Dictionary now, not a global.
#define ROTATELEFT tmp=t->right; t->right=tmp->left; tmp->left =t; t=tmp
#define ROTATERIGHT tmp=t->left; t->left =tmp->right; tmp->right=t; t=tmp
#define LINKLEFT tmp=t; t = t->right; l = l->right = tmp
#define LINKRIGHT tmp=t; t = t->left; r = r->left = tmp
#define ASSEMBLE r->left = t->right; l->right = t->left; \
t->left = Dummy->right; t->right = Dummy->left
// initialize the memory allocator for TreeNode
FreeListMgr TreeNode::MyFreeList( sizeof ( TreeNode ) );
//*************************************************************************
//***** Core functions (internal) *****
//*************************************************************************
SSIZE_T // return last comparision
Dictionary::SplayUserType( // general top down splay
pUserType keyItem // pointer to a "key item" searched for
) //-----------------------------------------------------------------------//
{ TreeNode* t; // current search point
TreeNode* l; // root of "left subtree" < keyItem
TreeNode* r; // root of "right subtree" > keyItem
SSIZE_T kcmp; // cash comparison results
TreeNode* tmp;
if ((fCompare = Compare(keyItem, root->item)) == 0) return (fCompare);
Dummy = l = r = &Dumbo; Dumbo.left = Dumbo.right = Nil;
t = root;
do { if ( fCompare < 0 ) { if ( t->left == Nil ) break;
if ( (kcmp = Compare(keyItem, t->left->item)) == 0 ) { LINKRIGHT; } else if ( kcmp < 0 ) { ROTATERIGHT; if ( t->left != Nil ) { LINKRIGHT; } } else { // keyItem > t->left->item
LINKRIGHT; if ( t->right != Nil ) { LINKLEFT; } } } else { // keyItem > t->item
if ( t->right == Nil ) break;
if ( (kcmp = Compare(keyItem, t->right->item)) == 0 ) { LINKLEFT; } else if ( kcmp > 0 ) { ROTATELEFT; if ( t->right != Nil ) { LINKLEFT; } } else { // keyItem < t->right->item
LINKLEFT; if ( t->left != Nil ) { LINKRIGHT; } } } } while ( (fCompare = Compare(keyItem, t->item)) != 0 );
ASSEMBLE;
// if (fCompare != Compare(keyItem, t->item))
// printf("Dictionary error!");
root = t; return(fCompare); }
//-----------------------------------------------------------------------
TreeNode * Dictionary::SplayLeft( TreeNode * t ) // root of tree & current "search" point
{ TreeNode * l = Dummy; // root of "left subtree" < keyItem
TreeNode * r = Dummy; // root of "right subtree" > keyItem
TreeNode * tmp;
if (t == Nil || t->left == Nil) return(t);
if (t->left->left == Nil) { ROTATERIGHT; return(t); }
Dummy->left = Dummy->right = Nil;
while ( t->left != Nil ) { ROTATERIGHT;
if ( t->left != Nil ) { LINKRIGHT; } } ASSEMBLE; return(t); }
#ifndef DICT_NOPREV
//-----------------------------------------------------------------------
TreeNode * Dictionary::SplayRight( TreeNode * t ) // root of tree & current "search" point
{ TreeNode * l = Dummy; // root of "left subtree" < keyItem
TreeNode * r = Dummy; // root of "right subtree" > keyItem
TreeNode * tmp;
if (t == Nil || t->right == Nil) return(t);
Dummy->left = Dummy->right = Nil;
while ( t->right != Nil ) { ROTATELEFT;
if ( t->right != Nil ) { LINKLEFT; } } ASSEMBLE; return(t); }
#endif
// Class methods for Splay Tree
Dict_Status Dictionary::Dict_Find( // return a item that matches
pUserType itemI // this value
// Returns:
// itemCur - Nil if at not in Dict, else found item
) //-----------------------------------------------------------------------//
{ itemCur = Nil;
if (root == Nil) return (EMPTY_DICTIONARY);
if (itemI == Nil) return (NULL_ITEM);
if (SplayUserType (itemI) == 0){
itemCur = root->item; return(SUCCESS); } // printf("After NotFound %ld: (", this); PrintItem(itemI); printf(")\n"); Dict_Print();
return(ITEM_NOT_FOUND); }
#ifndef DICT_NONEXT
Dict_Status Dictionary::Dict_Next( // return the next item
pUserType itemI // of a key greater then this
// Returns:
// itemCur - Nil if at end of Dict, else current item
) //-----------------------------------------------------------------------//
{ TreeNode* t;
itemCur = Nil;
if (root == Nil) return (EMPTY_DICTIONARY);
if (itemI == Nil) { // no arg, return first record
root = SplayLeft (root);
itemCur = root->item; return (SUCCESS); }
if (itemI != root->item)
if (SplayUserType (itemI) > 0) { itemCur = root->item; return (SUCCESS); }
if (root->right == Nil) return (LAST_ITEM);
t = root;
root = SplayLeft (root->right); root->left = t; t->right = Nil;
itemCur = root->item; return (SUCCESS); } #endif // DICT_NONEXT
#ifndef DICT_NOPREV
Dict_Status Dictionary::Dict_Prev( // return the previous item
pUserType itemI // of a key less then this
// Returns:
// itemCur - Nil if at begining of Dict, else current item
) //-----------------------------------------------------------------------//
{ TreeNode* t;
itemCur = Nil;
if (root == Nil) return (EMPTY_DICTIONARY);
if (itemI == Nil) { // no arg, return last record
root = SplayRight (root);
itemCur = root->item; return (SUCCESS); }
if (itemI != root->item)
if (SplayUserType (itemI) < 0) { itemCur = root->item; return (SUCCESS); }
if (root->left == Nil) return (LAST_ITEM);
t = root; root = SplayRight (root->left); root->right = t; t->left = Nil;
itemCur = root->item; return (SUCCESS); }
#endif // DICT_NOPREV
Dict_Status Dictionary::Dict_Insert( // insert the given item into the tree
pUserType itemI // the item to be inserted
// Returns:
// itemCur - point to new item
) //-----------------------------------------------------------------------//
{ TreeNode *newNode, *t;
if ((itemCur = itemI) == Nil) return (NULL_ITEM);
if (root == Nil) { root = new TreeNode(itemI); size++; return (SUCCESS); }
if (SplayUserType (itemI) == 0) return (ITEM_ALREADY_PRESENT);
newNode = new TreeNode(itemI); size++;
t = root;
if (fCompare > 0) { newNode->right = t->right; // item >= t->item
newNode->left = t; t->right = Nil; } else { newNode->left = t->left; newNode->right = t; t->left = Nil; } root = newNode;
// printf("After Insert %ld: (", this); PrintItem(itemI); printf(")\n"); Dict_Print();
return (SUCCESS); }
Dict_Status Dictionary::Dict_Delete( // delete the given item from the tree
pUserType *itemI // points to the (key) item to be deleted
// Returns:
// itemCur is Nil - undefined
) //-----------------------------------------------------------------------//
{ TreeNode *t, *r;
itemCur = Nil;
if (root == Nil) return (EMPTY_DICTIONARY);
if (itemI == Nil) return (NULL_ITEM);
if (itemI != root->item) {
if (SplayUserType (*itemI) != 0) return(ITEM_NOT_FOUND); }
*itemI = root->item; t = root;
if (t->left == Nil) root = t->right;
else if ( (r = t->right) == Nil) root = t->left;
else { r = SplayLeft (r); r->left = t->left; // at this point r->left == Nil
root = r; }
delete t; size--;
return (SUCCESS); }
pUserType Dictionary::Dict_Delete_One() { TreeNode * pCurrent = root; TreeNode * pPrev = NULL; // NULL indicates prev is root
pUserType pResult; BOOL fLeft = FALSE;
while ( pCurrent ) { if ( pCurrent->left ) { pPrev = pCurrent; pCurrent = pCurrent->left; fLeft = TRUE; continue; }
if ( pCurrent->right ) { pPrev = pCurrent; pCurrent = pCurrent->right; fLeft = FALSE; continue; }
// found a leaf
break; }
// we are now at a leaf (or tree empty)
if ( !pCurrent ) return NULL;
// unhook from parent
if ( pPrev ) { if ( fLeft ) pPrev->left = NULL; else pPrev->right = NULL; } else root = NULL;
// return the item, and delete the treenode
pResult = pCurrent->item; delete pCurrent; size--; return pResult; }
short Dictionary::Dict_GetList( gplistmgr & ListIter ) { pUserType pN; Dict_Status Status; short Count = 0;
// Get to the top of the dictionary.
Status = Dict_Next( (pUserType)0 );
// make sure we start with a clean iterator
ITERATOR_DISCARD( ListIter );
// Iterate till the entire dictionary is looked at.
while( SUCCESS == Status ) { pN = Dict_Curr_Item(); ListIter.Insert( pN ); Count++; Status = Dict_Next( pN ); }
return Count; }
// Utility functions to print of a tree
#ifndef DICT_NOPRINT
static indentCur; static PrintFN printCur;
static char spaces[] = " ";
void Dictionary::PrinTree( // recursively print out a tree
int lmargin, // current depth & margen
TreeNode *np // subtree to print
) //-----------------------------------------------------------------------//
{ if (np == Nil) return;
PrinTree(lmargin+indentCur, np->right);
if (lmargin > sizeof(spaces)) lmargin = sizeof(spaces);;
spaces[lmargin] = 0; printf(spaces); spaces[lmargin] = ' ';
Print(np->item); printf("\n");
PrinTree(lmargin+indentCur, np->left);
}
void Dictionary::Dict_Print( long indent
// prints the binary tree (indented right subtree,
// followed by the root, followed by the indented right dubtree)
) //-----------------------------------------------------------------------//
{ indentCur = indent;
PrinTree(0, root); }
#endif // DICT_PRINT
|