Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

790 lines
16 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1994 - 1995.
//
// File: avl.cxx
//
// Contents:
//
// Classes:
//
// Functions:
//
// History: 6/25/1995 RaviR Created
//
//----------------------------------------------------------------------------
#include "headers.hxx"
#pragma hdrstop
//#include "memory.hxx"
#include "dbg.h"
#include "macros.h"
#include "avl.hxx"
//+---------------------------------------------------------------------------
//
// Member: CAVLTree::Insert
//
// Synopsis: Insert the given atom in the tree.
//
// Arguments: [pa] -- IN The atom to insert.
//
// Returns: HRESULT.
//
// History: 8/29/1995 RaviR Created
//
//----------------------------------------------------------------------------
HRESULT
CAVLTree::Insert(
PAVLNODEATOM pa)
{
_hrInsert = S_OK;
_Insert(&_pFirstNode, pa);
if (_pFirstNode != NULL)
{
_pFirstNode->SetParent(NULL);
}
return _hrInsert;
}
//+---------------------------------------------------------------------------
//
// Member: CAVLTree::_Insert
//
// Synopsis: A recursive function to insert the given atom.
//
// Arguments: [ppNode] -- The root of the current tree.
// [pa] -- The atom to insert.
//
// Returns: TRUE if height changed, FALSE otherwise.
//
// History: 8/29/1995 RaviR Created
//
//----------------------------------------------------------------------------
BOOL
CAVLTree::_Insert(
CTreeNode ** ppNode,
PAVLNODEATOM pa)
{
CTreeNode *t = *ppNode;
CTreeNode *t1 = NULL;
CTreeNode *t2 = NULL;
if (t == NULL)
{
CTreeNode * ptn = new CTreeNode(pa);
if (ptn == NULL)
{
_hrInsert = E_OUTOFMEMORY;
CHECK_HRESULT(_hrInsert);
return FALSE;
}
*ppNode = ptn;
return TRUE;
}
BOOL fHeightChanged = FALSE;
int iComp = pa->Compare(t->Atom());
if (iComp < 0)
{
fHeightChanged = _Insert(&(t->_l), pa);
t->_l->SetParent(t);
if (fHeightChanged == TRUE)
{
switch (t->Balance())
{
case 1:
t->SetBalance(0);
fHeightChanged = FALSE;
break;
case 0:
t->SetBalance(-1);
// fHeightChanged = TRUE; // already TRUE
break;
case -1:
// Reblance
t1 = t->Left();
if (t1->Balance() == -1)
{
t->SetLeft(t1->Right());
t->SetBalance(0);
t1->SetRight(t);
t1->SetBalance(0);
t = t1;
fHeightChanged = FALSE;
}
else
{
Win4Assert(t1->Balance() == 1);
t2 = t1->Right();
t->SetLeft(t2->Right());
t1->SetRight(t2->Left());
t2->SetLeft(t1);
t2->SetRight(t);
if (t2->Balance() == -1)
{
t->SetBalance(1);
t1->SetBalance(0);
}
else if (t2->Balance() == 1)
{
t->SetBalance(0);
t1->SetBalance(-1);
}
else
{
Win4Assert(t2->Balance() == 0);
Win4Assert(t->Left() == NULL);
Win4Assert(t->Right() == NULL);
Win4Assert(t1->Right() == NULL);
Win4Assert(t1->Left() == NULL);
t->SetBalance(0);
t1->SetBalance(0);
}
t = t2;
t->SetBalance(0);
fHeightChanged = FALSE;
}
break;
default:
Win4Assert(0 && "Unknown balance!");
break;
}
}
}
else if (iComp > 0)
{
fHeightChanged = _Insert(&(t->_r), pa);
t->_r->SetParent(t);
if (fHeightChanged == TRUE)
{
switch (t->Balance())
{
case -1:
t->SetBalance(0);
fHeightChanged = FALSE;
break;
case 0:
t->SetBalance(1);
// fHeightChanged = TRUE; // already TRUE
break;
case 1:
// Rebalance
t1 = t->Right();
if (t1->Balance() == 1)
{
t->SetRight(t1->Left());
t->SetBalance(0);
t1->SetLeft(t);
t1->SetBalance(0);
t = t1;
fHeightChanged = FALSE;
}
else
{
Win4Assert(t1->Balance() == -1);
t2 = t1->Left();
t->SetRight(t2->Left());
t1->SetLeft(t2->Right());
t2->SetLeft(t);
t2->SetRight(t1);
if (t2->Balance() == -1)
{
t->SetBalance(0);
t1->SetBalance(1);
}
else if (t2->Balance() == 1)
{
t->SetBalance(-1);
t1->SetBalance(0);
}
else
{
Win4Assert(t2->Balance() == 0);
Win4Assert(t->Left() == NULL);
Win4Assert(t->Right() == NULL);
Win4Assert(t1->Right() == NULL);
Win4Assert(t1->Left() == NULL);
t->SetBalance(0);
t1->SetBalance(0);
}
t2->SetBalance(0);
t = t2;
fHeightChanged = FALSE;
}
break;
default:
Win4Assert(0 && "Unknown balance!");
break;
}
}
}
else
{
_hrInsert = S_FALSE;
}
*ppNode = t;
return fHeightChanged;
}
void
CAVLTree::Delete(
PAVLNODEATOM pa)
{
_Delete(&_pFirstNode, pa);
if (_pFirstNode != NULL)
{
_pFirstNode->SetParent(NULL);
}
}
BOOL
CAVLTree::_Delete(
CTreeNode ** ppNode,
PAVLNODEATOM pa)
{
CTreeNode *t = *ppNode;
if (t == NULL)
{
return FALSE;
}
CTreeNode *lt = t->Left();
CTreeNode *rt = t->Right();
CTreeNode *ct;
CTreeNode *tToDel;
PAVLNODEATOM paTemp = NULL;
BOOL fHeightChanged = FALSE; // value to return
BOOL fTemp;
int iComp = pa->Compare(t->Atom());
if (iComp == 0)
{
if (lt == NULL)
{
tToDel = t;
t = rt;
tToDel->SetLeft(NULL);
tToDel->SetRight(NULL);
delete tToDel;
fHeightChanged = TRUE;
}
else if (rt == NULL)
{
tToDel = t;
t = lt;
tToDel->SetLeft(NULL);
tToDel->SetRight(NULL);
delete tToDel;
fHeightChanged = TRUE;
}
else
{
switch (t->Balance())
{
case -1:
paTemp = lt->GetMax();
fTemp = _Delete(&t->_l, paTemp);
if (t->_l)
{
t->_l->SetParent(t);
}
if (fTemp == TRUE)
{
t->SetBalance(0);
fHeightChanged = TRUE;
}
break;
case 0:
paTemp = lt->GetMax();
fTemp = _Delete(&t->_l, paTemp);
if (t->_l)
{
t->_l->SetParent(t);
}
if (fTemp == TRUE)
{
t->SetBalance(1);
}
break;
case 1:
paTemp = rt->GetMin();
fTemp = _Delete(&t->_r, paTemp);
if (t->_r)
{
t->_r->SetParent(t);
}
if (fTemp == TRUE)
{
t->SetBalance(0);
fHeightChanged = TRUE;
}
break;
}
t->SetAtom(paTemp);
}
}
else if (iComp > 0)
{
fTemp = _Delete(&t->_r, pa);
if (t->_r)
{
t->_r->SetParent(t);
}
if (fTemp == TRUE)
{
switch (t->Balance())
{
case 1:
t->SetBalance(0);
fHeightChanged = TRUE;
break;
case 0:
t->SetBalance(-1);
break;
case -1:
switch (lt->Balance())
{
case -1:
t->SetLeft(lt->Right());
t->SetParent(lt);
lt->SetRight(t);
t->SetBalance(0);
lt->SetBalance(0);
t = lt;
fHeightChanged = TRUE;
break;
case 0:
t->SetLeft(lt->Right());
t->SetParent(lt);
lt->SetRight(t);
t->SetBalance(-1);
lt->SetBalance(1);
t = lt;
break;
case 1:
ct = lt->Right();
Win4Assert(ct != NULL); // becos (lt->Balance() == 1)
t->SetLeft(ct->Right());
t->SetParent(ct);
lt->SetRight(ct->Left());
lt->SetParent(ct);
ct->SetLeft(lt);
ct->SetRight(t);
switch (ct->Balance())
{
case -1:
lt->SetBalance(0);
t->SetBalance(1);
break;
case 0:
lt->SetBalance(0);
t->SetBalance(0);
break;
case 1:
lt->SetBalance(-1);
t->SetBalance(0);
break;
}
ct->SetBalance(0);
t = ct;
fHeightChanged = TRUE;
break;
}
break;
}
}
}
else // if (iComp < 0)
{
fTemp = _Delete(&t->_l, pa);
if (t->_l)
{
t->_l->SetParent(t);
}
if (fTemp == TRUE)
{
switch (t->Balance())
{
case -1:
t->SetBalance(0);
fHeightChanged = TRUE;
break;
case 0:
t->SetBalance(1);
break;
case 1:
switch (rt->Balance())
{
case 1:
t->SetRight(rt->Left());
t->SetParent(rt);
rt->SetLeft(t);
t->SetBalance(0);
rt->SetBalance(0);
t = rt;
fHeightChanged = TRUE;
break;
case 0:
t->SetRight(rt->Left());
t->SetParent(rt);
rt->SetLeft(t);
t->SetBalance(1);
rt->SetBalance(-1);
t = rt;
break;
case -1:
ct = rt->Left();
Win4Assert(ct != NULL); // becos (rt->Balance() == -1)
t->SetRight(ct->Left());
t->SetParent(ct);
rt->SetLeft(ct->Right());
rt->SetParent(ct);
ct->SetLeft(t);
ct->SetRight(rt);
switch (ct->Balance())
{
case -1:
t->SetBalance(0);
rt->SetBalance(1);
break;
case 0:
t->SetBalance(0);
rt->SetBalance(0);
break;
case 1:
t->SetBalance(-1);
rt->SetBalance(0);
break;
}
ct->SetBalance(0);
t = ct;
fHeightChanged = TRUE;
break;
}
break;
}
}
}
*ppNode = t;
return fHeightChanged;
}
//+---------------------------------------------------------------------------
//
// Member: CAVLTree::GetAtom
//
// Arguments: [pa] -- Atom
//
// Returns: The TreeNode containig the atom.
//
// History: 8/29/1995 RaviR Created
//
//----------------------------------------------------------------------------
PAVLNODEATOM
CAVLTree::GetAtom(
PAVLNODEATOM pa)
{
CTreeNode *t = _pFirstNode;
while (t != NULL)
{
int iComp = pa->Compare(t->Atom());
if (iComp == 0)
{
return t->Atom();
}
else if (iComp < 0)
{
t = t->Left();
continue;
}
else
{
t = t->Right();
continue;
}
}
return NULL;
}
//+---------------------------------------------------------------------------
//
// Member: CAVLTree::GetFirst
//
// Synopsis: Returns the first atom in the tree.
//
// History: 8/29/1995 RaviR Created
//
//----------------------------------------------------------------------------
PAVLNODEATOM
CAVLTree::GetFirst(void)
{
if (_pFirstNode == NULL)
{
return NULL;
}
_pFirstNode->ResetTraversedFlag();
CTreeNode *t = _pFirstNode;
while (t->Left() != NULL)
{
t = t->Left();
}
_pCurrentNode = t;
t->SetTraversed();
return t->Atom();
}
//+---------------------------------------------------------------------------
//
// Member: CAVLTree::GetNext
//
// Synopsis: Traverses the tree inorder.
//
// History: 8/29/1995 RaviR Created
//
//----------------------------------------------------------------------------
PAVLNODEATOM
CAVLTree::GetNext(void)
{
CTreeNode *t = _pCurrentNode;
do
{
if (t->Right() != NULL)
{
t = t->Right();
while (t->Left() != NULL)
{
t = t->Left();
}
}
else
{
t = t->Parent();
while (t != NULL && t->IsTraversed())
{
t = t->Parent();
}
}
} while (0);
_pCurrentNode = t;
if (t != NULL)
{
t->SetTraversed();
return t->Atom();
}
return NULL;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#if (DBG == 1)
void
CTreeNode::Dump(void)
{
if (_l)
{
_l->Dump();
}
//printf("<val, bal> = <");
_pa->Dump();
//printf(", %d>\n", (UINT)_b);
if (_r)
{
_r->Dump();
}
}
void
CAVLTree::Dump(void)
{
DEBUG_OUT((DEB_USER1, "Start Dump:\n"));
if (_pFirstNode != NULL)
{
_pFirstNode->Dump();
}
DEBUG_OUT((DEB_USER1, "End Dump.\n"));
}
#endif