4.16 Redo the binary search tree class to implement lazy deletion. Note carefully that this affects all of the routines. Especially challenging are findMin and findMax, which must now be done recursively.
4.21 Write the remaining procedures to implement AVL single and double rotations.
4.22 Design a linear-time algorithm that verifies that the height information in an AVL tree is correctly maintained and that the balance property is in order.
//4.16 bstree.hpp
#ifndef BSTREE_HPP__
#define BSTREE_HPP__
#include <iosfwd>
template< typename Object >
class Set;
template< typename Object >
class BSTree {
private:
class Node {
public:
Node(const Object& val = Object(), Node* l = NULL, Node* r = NULL,
bool e = false) : lChild(l),
rChild(r), data(val), erased(e)
{}
Node& operator=(const Node& rhs)
{
data = rhs.data;
lChild = rhs.lChild;
rChild = rhs.rChild;
erased = rhs.erased;
}
public:
Object data;
Node* lChild;
Node* rChild;
bool erased;
};
public:
BSTree() : root(NULL), theSize(0), numErased(0), min(NULL),
max(NULL) {}
~BSTree(){ clear(); }
BSTree(const BSTree& rhs){}
BSTree& operator=(const BSTree& rhs){}
public:
bool contains(const Object& val) const
{ return contains(val, root); }
bool empty() const
{ return theSize == 0; }
void printTree(std::ostream& out, bool flag = false)
{
if(empty())
out << "empty tree/n";
else
printTree(root, out, flag);
}
void clear()
{ clear(root); }
void add(const Object& val)
{ insert(val, root); }
void del(const Object& val)
{ remove(val, root); }
Object findMin()
{
min = NULL;
findMin(root, min);
return min->data;
}
Object findMax()
{
max = NULL;
findMax(root, max);
return max->data;
}
private:
void insert(const Object& val, Node* &t)
{
if(t == NULL)
{
t = new Node(val, NULL, NULL);
++theSize;
}
else if(val < t->data)
insert(val, t->lChild);
else if(t->data < val)
insert(val, t->rChild);
else if(t->erased == true)
{
t->erased = false;
++theSize;
--numErased;
}
}
void remove(const Object& val, Node* &t)
{
if(t == NULL)
return;
if(val < t->data)
remove(val, t->lChild);
else if(t->data < val)
remove(val, t->rChild);
else if(theSize <= numErased && numErased != 0)
{
t->erased = true;
--theSize;
++numErased;
doRemove(root);
}
else
{
t->erased = true;
++numErased;
--theSize;
}
}
void doRemove(Node* &t)
{
if(t != NULL)
{
doRemove(t->lChild);
doRemove(t->rChild);
if(t->erased == true)
{
removeA(t->data, root);
--numErased;
}
}
}
void removeA(const Object& val, Node* &t)
{
if(t == NULL)
return;
if(val < t->data)
removeA(val, t->lChild);
else if(t->data < val)
removeA(val, t->rChild);
else if(t->lChild != NULL && t->rChild != NULL)
{
Node* p;
t->data = findMin(t->rChild)->data;
p = findMin(t->rChild);
t->erased = p->erased;
p->erased = true;
removeA(t->data, t->rChild);
}
else
{
Node* old = t;
t = (t->lChild != NULL) ? t->lChild : t->rChild;
delete old;
}
}
bool contains(const Object& val, Node* t) const
{
if(t == NULL)
return false;
else if(val < t->data)
return contains(val, t->lChild);
else if(t->data < val)
return contains(val, t->rChild);
else if(t->erased == false)
return true;
else
return false;
}
Node* findMin(Node* t)
{
if(t == NULL)
return NULL;
if(t->lChild == NULL)
return t;
return findMin(t->lChild);
}
void findMin(Node* t, Node* &m)
{
if(t != NULL)
{
findMin(t->lChild, m);
if(t->erased == false)
{
if(m == NULL || m->data > t->data)
m = t;
}
findMin(t->rChild, m);
}
}
void findMax(Node* t, Node* &m)
{
if(t != NULL)
{
findMax(t->rChild, m);
if(t->erased == false)
{
if(m == NULL || m->data < t->data)
m = t;
}
findMax(t->lChild, m);
}
}
void clear(Node* &t)
{
if(t != NULL)
{
clear(t->lChild);
clear(t->rChild);
delete t;
}
t = NULL;
}
void printTree(Node* t, std::ostream& out, bool flag)
{
if(t != NULL)
{
printTree(t->lChild, out, flag);
if(flag)
out << t->data << "/n";
else
{
if(t->erased == false)
out << t->data << "/n";
}
printTree(t->rChild, out, flag);
}
}
private:
Node* root;
Node* min;
Node* max;
int theSize;
int numErased;
friend class Set<Object>;
};
#endif
//4.21-4.22 avltree.hpp
#ifndef AVLTREE_HPP__
#define AVLTREE_HPP__
#include <iostream>
template <typename Object>
class AvlTree
{
public:
AvlTree( ) : root( NULL )
{ }
AvlTree( const AvlTree & rhs ) : root( NULL )
{
*this = rhs;
}
~AvlTree( )
{
makeEmpty( );
}
const Object & findMin( ) const
{
if( isEmpty( ) )
std::cerr << "Underflow/n";
return findMin( root )->element;
}
const Object & findMax( ) const
{
if( isEmpty( ) )
std::cerr << "Underflow/n";
return findMax( root )->element;
}
bool contains( const Object & x ) const
{
return contains( x, root );
}
bool isEmpty( ) const
{
return root == NULL;
}
void printTree( ) const
{
if( isEmpty( ) )
std::cout << "Empty tree" << std::endl;
else
printTree( root );
}
void makeEmpty( )
{
makeEmpty( root );
}
void insert( const Object & x )
{
insert( x, root );
}
void remove( const Object & x )
{
cout << "Sorry, remove unimplemented; " << x <<
" still present" << endl;
}
const AvlTree & operator=( const AvlTree & rhs )
{
if( this != &rhs )
{
makeEmpty( );
root = clone( rhs.root );
}
return *this;
}
void printHeight()
{
int rHeight = -1, lHeight = -1;
if(root->right != NULL)
rHeight = height(root->right);
if(root->left != NULL)
lHeight = height(root->left);
std::cout << "Height of left sub-tree: "
<< lHeight << "/tHeight of right sub-tree: "
<< rHeight << "/n" << "root height: "
<< root->height;
}
private:
struct AvlNode
{
Object element;
AvlNode *left;
AvlNode *right;
int height;
AvlNode( const Object & theElement, AvlNode *lt,
AvlNode *rt, int h = 0 )
: element( theElement ), left( lt ), right( rt ), height( h ) { }
};
AvlNode *root;
void insert( const Object & x, AvlNode * & t )
{
if( t == NULL )
t = new AvlNode( x, NULL, NULL );
else if( x < t->element )
{
insert( x, t->left );
if( height( t->left ) - height( t->right ) == 2 )
if( x < t->left->element )
rotateWithLeftChild( t );
else
doubleWithLeftChild( t );
}
else if( t->element < x )
{
insert( x, t->right );
if( height( t->right ) - height( t->left ) == 2 )
if( t->right->element < x )
rotateWithRightChild( t );
else
doubleWithRightChild( t );
}
else
;
t->height = max( height( t->left ), height( t->right ) ) + 1;
}
AvlNode * findMin( AvlNode *t ) const
{
if( t == NULL )
return NULL;
if( t->left == NULL )
return t;
return findMin( t->left );
}
AvlNode * findMax( AvlNode *t ) const
{
if( t != NULL )
while( t->right != NULL )
t = t->right;
return t;
}
bool contains( const Object & x, AvlNode *t ) const
{
if( t == NULL )
return false;
else if( x < t->element )
return contains( x, t->left );
else if( t->element < x )
return contains( x, t->right );
else
return true; // Match
}
void makeEmpty( AvlNode * & t )
{
if( t != NULL )
{
makeEmpty( t->left );
makeEmpty( t->right );
delete t;
}
t = NULL;
}
void printTree( AvlNode *t ) const
{
if( t != NULL )
{
printTree( t->left );
std::cout << t->element << std::endl;
printTree( t->right );
}
}
AvlNode * clone( AvlNode *t ) const
{
if( t == NULL )
return NULL;
else
return new AvlNode( t->element, clone( t->left ), clone( t->right ), t->height );
}
// Avl manipulations
int height( AvlNode *t ) const
{
return t == NULL ? -1 : t->height;
}
int max( int lhs, int rhs ) const
{
return lhs > rhs ? lhs : rhs;
}
void rotateWithLeftChild( AvlNode * & k2 )
{
AvlNode *k1 = k2->left;
k2->left = k1->right;
k1->right = k2;
k2->height = max( height( k2->left ), height( k2->right ) ) + 1;
k1->height = max( height( k1->left ), k2->height ) + 1;
k2 = k1;
}
void rotateWithRightChild( AvlNode * & k1 )
{
AvlNode *k2 = k1->right;
k1->right = k2->left;
k2->left = k1;
k1->height = max( height( k1->left ), height( k1->right ) ) + 1;
k2->height = max( height( k2->right ), k1->height ) + 1;
k1 = k2;
}
void doubleWithLeftChild( AvlNode * & k3 )
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 );
}
void doubleWithRightChild( AvlNode * & k1 )
{
rotateWithLeftChild( k1->right );
rotateWithRightChild( k1 );
}
};
#endif