home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1998 May
/
Pcwk5b98.iso
/
Borland
/
Cplus45
/
BC45
/
CLOBSS.PAK
/
BTREELFN.CPO
< prev
next >
Wrap
Text File
|
1995-08-29
|
11KB
|
360 lines
/*------------------------------------------------------------------------*/
/* */
/* BTREELFN.CPP */
/* */
/* Copyright Borland International 1991, 1993 */
/* All Rights Reserved */
/* */
/*------------------------------------------------------------------------*/
#if !defined( __STDLIB_H )
#include <stdlib.h>
#endif // __STDLIB_H
#if !defined( __IOSTREAM_H )
#include <iostream.h>
#endif // __IOSTREAM_H
#if !defined( CHECKS_H )
#include <checks.h>
#endif // CHECKS_H
#if !defined( __BTREE_H )
#include "classlib\obsolete\btree.h"
#endif // __BTREE_H
//====== LeafNode functions =======
LeafNode::LeafNode(InnerNode* P, Sortable* O, Btree* T): Node(1, P, T)
{
item = new Sortable *[maxIndex()+1];
if( item == 0 )
ClassLib_error( __ENOMEMLN );
if( O != 0 )
item[++last] = O;
}
LeafNode::~LeafNode()
{
if( tree->ownsElements() )
{
for( int i = 0; i <= last; i++ )
delete item[i];
}
delete [] item;
}
void LeafNode::add(Sortable *obj, int index)
{
// add the object OBJ to the leaf node, inserting it at location INDEX
// in the item array
PRECONDITION( 0 <= index && index <= last+1 );
PRECONDITION( last <= maxIndex() );
for( int i = last+1; i > index ; i-- )
item[i] = item[ i - 1 ];
item[ index ] = obj;
last++;
// check for overflow
if( parent == 0 )
tree->incrNofKeys( );
else
parent->incrNofKeys( this );
if( isFull() )
{
// it's full; tell parent node
if( parent == 0 )
{
// this occurs when this leaf is the only node in the
// btree, and this->tree->root == this
CHECK( tree->root == this );
// in which case we inform the btree, which can be
// considered the parent of this node
tree->rootIsFull();
}
else
{
// the parent is responsible for splitting/balancing subnodes
parent->isFull( this );
}
}
}
void LeafNode::appendFrom( LeafNode* src, int start, int stop )
{
// A convenience function, does not worry about the element in
// the parent, simply moves elements from SRC[start] to SRC[stop]
// into the current array.
// This should never create a full node.
// That is, it is not used anywhere where THIS could possibly be
// near full.
// Does NOT handle nofKeys.
if( start > stop )
return;
PRECONDITION( 0 <= start && start <= src->last );
PRECONDITION( 0 <= stop && stop <= src->last );
PRECONDITION( last + stop - start + 1 < maxIndex() ); // full-node check
for( int i = start; i <= stop; i++ )
item[++last] = src->item[i];
CHECK( last < maxIndex() );
}
void LeafNode::append( Sortable* D )
{
// never called from anywhere where it might fill up THIS
// does NOT handle nofKeys.
item[++last] = D;
CHECK( last < maxIndex() );
}
void LeafNode::balanceWithLeft( LeafNode* leftsib, int pidx )
{
// THIS has more than LEFTSIB; move some items from THIS to LEFTSIB.
PRECONDITION( Vsize() >= leftsib->Psize() );
int newThisSize = (Vsize() + leftsib->Psize())/2;
int noFromThis = Psize() - newThisSize;
pushLeft( noFromThis, leftsib, pidx );
}
void LeafNode::balanceWithRight( LeafNode* rightsib, int pidx )
{
// THIS has more than RIGHTSIB; move some items from THIS to RIGHTSIB.
PRECONDITION( Psize() >= rightsib->Vsize() );
int newThisSize = (Psize() + rightsib->Vsize())/2;
int noFromThis = Psize() - newThisSize;
pushRight( noFromThis, rightsib, pidx );
}
void LeafNode::balanceWith( LeafNode* rightsib, int pidx )
{
// PITEM is the parent item whose key will change when keys are shifted
// from one LeafNode to the other.
if( Psize() < rightsib->Vsize() )
rightsib->balanceWithLeft( this, pidx );
else
balanceWithRight( rightsib, pidx );
}
long LeafNode::findRank( Sortable* what ) const
{
// WHAT was not in any inner node; it is either here, or it's
// not in the tree
for( int i = 0; i <= last; i++ )
{
if( *item[i] == *what )
return i;
if( *item[i] >= *what )
return -1;
}
return -1;
}
LeafNode *LeafNode::firstLeafNode()
{
return this;
}
Object& LeafNode::found(Sortable* what, Node** which, int* where )
{
// WHAT was not in any inner node; it is either here, or it's
// not in the tree
for( int i = 0; i <= last; i++ )
{
if( *item[i] == *what )
{
*which = this;
*where = i;
return *item[i];
}
if( *item[i] >= *what )
{
*which = this;
*where = i;
return NOOBJECT;
}
}
*which = this;
*where = last+1;
return NOOBJECT;
}
#pragma warn -rvl
int LeafNode::indexOf( const Sortable *that ) const
{
// returns a number in the range 0 to maxIndex()
for( int i = 0; i <= last; i++ )
{
if( item[i] == that )
return i;
}
CHECK(0);
}
#pragma warn .rvl
LeafNode *LeafNode::lastLeafNode()
{
return this;
}
void LeafNode::mergeWithRight( LeafNode* rightsib, int pidx )
{
PRECONDITION( Psize() + rightsib->Vsize() < maxPsize() );
rightsib->pushLeft( rightsib->Psize(), this, pidx );
append( parent->getKey( pidx ) );
parent->setNofKeys( pidx-1, nofKeys() );
// cout << "in mergeWithRight:\n" << *parent << "\n";
parent->removeItem( pidx );
delete rightsib;
// cout << "in mergeWithRight:\n" << *parent << "\n";
}
long LeafNode::nofKeys( int ) const
{
return 1;
}
long LeafNode::nofKeys() const
{
return Psize();
}
void LeafNode::printOn(ostream& out) const
{
out << " < ";
for( int i = 0; i <= last; i++ )
out << *item[i] << " " ;
out << "> ";
}
void LeafNode::pushLeft( int noFromThis, LeafNode* leftsib, int pidx )
{
// noFromThis==1 => moves the parent item into the leftsib,
// and the first item in this's array into the parent item
PRECONDITION( noFromThis > 0 && noFromThis <= Psize() );
PRECONDITION( noFromThis + leftsib->Psize() < maxPsize() );
PRECONDITION( parent->getTree(pidx) == this );
leftsib->append( parent->getKey(pidx) );
if( noFromThis > 1 )
leftsib->appendFrom( this, 0, noFromThis-2 );
parent->setKey( pidx, item[noFromThis-1] );
shiftLeft( noFromThis );
parent->setNofKeys( pidx-1, leftsib->nofKeys() );
parent->setNofKeys( pidx, nofKeys() );
}
void LeafNode::pushRight( int noFromThis, LeafNode* rightsib, int pidx )
{
// noFromThis==1 => moves the parent item into the
// rightsib, and the last item in this's array into the parent
// item
PRECONDITION(noFromThis > 0 && noFromThis <= Psize());
PRECONDITION(noFromThis + rightsib->Psize() < maxPsize());
PRECONDITION(parent->getTree(pidx) == rightsib);
// The operation is five steps:
// Step I. Make room for the incoming keys in RIGHTSIB.
// Step II. Move the key in the parent into RIGHTSIB.
// Step III.Move the items from THIS into RIGHTSIB.
// Step IV. Move the item from THIS into the parent.
// Step V. Update the length of THIS.
//
// Step I.: make space for noFromThis items
//
int start = last - noFromThis + 1;
int tgt, src;
tgt = rightsib->last + noFromThis;
src = rightsib->last;
rightsib->last = tgt;
while (src >= 0)
rightsib->item[tgt--] = rightsib->item[src--];
// Step II. Move the key from the parent into place
rightsib->item[ tgt-- ] = parent->getKey( pidx );
// Step III.Move the items from THIS into RIGHTSIB
for( int i = last; i > start; i-- )
rightsib->item[tgt--] = item[i];
CHECK( tgt == -1 );
// Step IV.
parent->setKey( pidx, item[ start ] );
// Step V.
last -= noFromThis;
// Step VI. update nofKeys
parent->setNofKeys( pidx-1, nofKeys() );
parent->setNofKeys( pidx, rightsib->nofKeys() );
}
void LeafNode::remove( int index )
{
PRECONDITION( index >= 0 && index <= last );
for( int to = index; to < last; to++ )
item[to] = item[to+1];
last--;
if( parent == 0 )
tree->decrNofKeys();
else
parent->decrNofKeys( this );
if( isLow() )
{
if( parent == 0 )
{
// then this is the root; when no keys left, inform the tree
if( Psize() == 0 )
tree->rootIsEmpty();
}
else
parent->isLow( this );
}
}
void LeafNode::shiftLeft( int cnt )
{
if( cnt <= 0 )
return;
for( int i = cnt; i <= last; i++ )
item[i-cnt] = item[i];
last -= cnt;
}
void LeafNode::split()
{
// this function is called only when THIS is the only descendent
// of the root node, and THIS needs to be split.
// assumes that idx of THIS in Parent is 0.
LeafNode* newnode = new LeafNode( parent );
CHECK( newnode != 0 );
parent->append( item[last--], newnode );
parent->setNofKeys( 0, parent->getTree(0)->nofKeys() );
parent->setNofKeys( 1, parent->getTree(1)->nofKeys() );
balanceWithRight( newnode, 1 );
}
void LeafNode::splitWith( LeafNode *rightsib, int keyidx )
{
PRECONDITION(parent == rightsib->parent);
PRECONDITION(keyidx > 0 && keyidx <= parent->last);
int nofKeys = Psize() + rightsib->Vsize();
int newSizeThis = nofKeys / 3;
int newSizeNew = (nofKeys - newSizeThis) / 2;
int newSizeSib = (nofKeys - newSizeThis - newSizeNew);
int noFromThis = Psize() - newSizeThis;
int noFromSib = rightsib->Vsize() - newSizeSib;
CHECK(noFromThis >= 0);
CHECK(noFromSib >= 1);
LeafNode* newNode = new LeafNode(parent);
CHECK( newNode != 0 );
parent->addElt( keyidx, item[last--], newNode );
parent->setNofKeys( keyidx, 0 );
parent->decNofKeys( keyidx-1 );
this->pushRight( noFromThis-1, newNode, keyidx );
rightsib->pushLeft( noFromSib, newNode, keyidx+1 );
if( parent->isFull() )
parent->informParent();
}