Source Code For Data Structures and Algorithm Analysis in C
Source Code For Data Structures and Algorithm Analysis in C
Source Code For Data Structures and Algorithm Analysis in C
VECTOR.H
#ifndef VECTOR_H
#define VECTOR_H
class ArrayIndexOutOfBounds { };
#include "vector.cpp"
#endif
VECTOR.CPP
#ifndef VECTOR_CPP_
#define VECTOR_CPP_
#include "vector.h"
#ifdef WIN32
if( currentSize != 0 )
#endif
delete [ ] oldArray;
currentSize = newSize;
}
#endif
Fig01_02.cpp: A simple recursive routine with a test
program
#include <iostream.h>
int f( int x )
{
/* 1*/ if( x == 0 )
/* 2*/ return 0;
else
/* 3*/ return 2 * f( x - 1 ) + x * x;
}
int main( )
{
cout << "f(5) = " << f( 5 ) << endl;
return 0;
}
#ifndef LinkedList_H
#define LinkedList_H
#include "dsexceptions.h"
#include <iostream.h> // For NULL
// List class
//
// CONSTRUCTION: with no initializer
// Access is via ListItr class
//
// ******************PUBLIC OPERATIONS*********************
// boolean isEmpty( ) --> Return true if empty; else false
// void makeEmpty( ) --> Remove all items
// ListItr zeroth( ) --> Return position to prior to first
// ListItr first( ) --> Return first position
// void insert( x, p ) --> Insert x after current iterator
position p
// void remove( x ) --> Remove x
// ListItr find( x ) --> Return position that views x
// ListItr findPrevious( x )
// --> Return position prior to x
// ******************ERRORS********************************
// No special errors
Object element;
ListNode *next;
private:
ListNode<Object> *header;
};
private:
ListNode<Object> *current; // Current position
#include "LinkedList.cpp"
#endif
LinkedList.cpp: Implementation for linked list
#include "LinkedList.h"
/**
* Construct the list
*/
template <class Object>
List<Object>::List( )
{
header = new ListNode<Object>;
}
/**
* Copy constructor
*/
template <class Object>
List<Object>::List( const List<Object> & rhs )
{
header = new ListNode<Object>;
*this = rhs;
}
/**
* Destructor
*/
template <class Object>
List<Object>::~List( )
{
makeEmpty( );
delete header;
}
/**
* Test if the list is logically empty.
* return true if empty, false otherwise.
*/
template <class Object>
bool List<Object>::isEmpty( ) const
{
return header->next == NULL;
}
/**
* Make the list logically empty.
*/
template <class Object>
void List<Object>::makeEmpty( )
{
while( !isEmpty( ) )
remove( first( ).retrieve( ) );
}
/**
* Return an iterator representing the header node.
*/
template <class Object>
ListItr<Object> List<Object>::zeroth( ) const
{
return ListItr<Object>( header );
}
/**
* Return an iterator representing the first node in the list.
* This operation is valid for empty lists.
*/
template <class Object>
ListItr<Object> List<Object>::first( ) const
{
return ListItr<Object>( header->next );
}
/**
* Insert item x after p.
*/
template <class Object>
void List<Object>::insert( const Object & x, const
ListItr<Object> & p )
{
if( p.current != NULL )
p.current->next = new ListNode<Object>( x, p.current-
>next );
}
/**
* Return iterator corresponding to the first node containing an
item x.
* Iterator isPastEnd if item is not found.
*/
template <class Object>
ListItr<Object> List<Object>::find( const Object & x ) const
{
/* 1*/ ListNode<Object> *itr = header->next;
/**
* Return iterator prior to the first node containing an item x.
*/
template <class Object>
ListItr<Object> List<Object>::findPrevious( const Object & x )
const
{
/* 1*/ ListNode<Object> *itr = header;
/**
* Remove the first occurrence of an item x.
*/
template <class Object>
void List<Object>::remove( const Object & x )
{
ListItr<Object> p = findPrevious( x );
/**
* Deep copy of linked lists.
*/
template <class Object>
const List<Object> & List<Object>::operator=( const List<Object>
& rhs )
{
ListItr<Object> ritr = rhs.first( );
ListItr<Object> itr = zeroth( );
#include <iostream.h>
#include "LinkedList.h"
int main( )
{
List<int> theList;
ListItr<int> theItr = theList.zeroth( );
int i;
printList( theList );
List<int> list2;
list2 = theList;
printList( list2 );
return 0;
}
Polynomial.cpp: Polynomials
/*
* This code doesn't really do much, and abstraction is not built
in.
* Thus, I haven't bothered testing it exhaustively.
*/
#include <iostream.h>
#include "vector.h"
class Polynomial
{
enum { MAX_DEGREE = 100 };
friend int main( ); // So I can do a quick test.
public:
Polynomial( );
void zeroPolynomial( );
Polynomial operator+( const Polynomial & rhs ) const;
Polynomial operator*( const Polynomial & rhs ) const;
void print( ostream & out ) const;
private:
vector<int> coeffArray;
int highPower;
};
void Polynomial::zeroPolynomial( )
{
for( int i = 0; i <= MAX_DEGREE; i++ )
coeffArray[ i ] = 0;
highPower = 0;
}
ostream & operator<<( ostream & out, const Polynomial & rhs )
{
rhs.print( out );
return out;
}
int main( )
{
Polynomial p;
Polynomial q;
q = p + p;
p = q * q;
q = p + p;
#ifndef CursorList_H
#define CursorList_H
#include "vector.h"
#include "dsexceptions.h"
public:
struct CursorNode
{
CursorNode( ) : next( 0 ) { }
private:
CursorNode( const Object & theElement, int n )
: element( theElement ), next( n ) { }
Object element;
int next;
private:
int header;
private:
int current; // Current position
friend class List<Object>;
#include "CursorList.cpp"
#endif
CursorList.cpp: Implementation for cursor linked list
#include "CursorList.h"
/**
* Routine to initialize the cursorSpace.
*/
template <class Object>
void List<Object>::initializeCursorSpace( )
{
static int cursorSpaceIsInitialized = false;
if( !cursorSpaceIsInitialized )
{
cursorSpace.resize( 100 );
for( int i = 0; i < cursorSpace.size( ); i++ )
cursorSpace[ i ].next = i + 1;
cursorSpace[ cursorSpace.size( ) - 1 ].next = 0;
cursorSpaceIsInitialized = true;
}
}
/**
* Allocate a CursorNode
*/
template <class Object>
int List<Object>::alloc( )
{
int p = cursorSpace[ 0 ].next;
cursorSpace[ 0 ].next = cursorSpace[ p ].next;
return p;
}
/**
* Free a CursorNode
*/
template <class Object>
void List<Object>::free( int p )
{
cursorSpace[ p ].next = cursorSpace[ 0 ].next;
cursorSpace[ 0 ].next = p;
}
/**
* Construct the list
*/
template <class Object>
List<Object>::List( )
{
initializeCursorSpace( );
header = alloc( );
cursorSpace[ header ].next = 0;
}
/**
* Copy constructor
*/
template <class Object>
List<Object>::List( const List<Object> & rhs )
{
initializeCursorSpace( );
header = alloc( );
cursorSpace[ header ].next = 0;
*this = rhs;
}
/**
* Destroy the list
*/
template <class Object>
List<Object>::~List( )
{
makeEmpty( );
free( header );
}
/**
* Test if the list is logically empty.
* return true if empty, false otherwise.
*/
template <class Object>
bool List<Object>::isEmpty( ) const
{
return cursorSpace[ header ].next == 0;
}
/**
* Make the list logically empty.
*/
template <class Object>
void List<Object>::makeEmpty( )
{
while( !isEmpty( ) )
remove( first( ).retrieve( ) );
}
/**
* Return an iterator representing the header node.
*/
template <class Object>
ListItr<Object> List<Object>::zeroth( ) const
{
return ListItr<Object>( header );
}
/**
* Return an iterator representing the first node in the list.
* This operation is valid for empty lists.
*/
template <class Object>
ListItr<Object> List<Object>::first( ) const
{
return ListItr<Object>( cursorSpace[ header ].next );
}
/**
* Insert item x after p.
*/
template <class Object>
void List<Object>::insert( const Object & x, const
ListItr<Object> & p )
{
if( p.current != 0 )
{
int pos = p.current;
int tmp = alloc( );
/**
* Return iterator corresponding to the first node containing an
item x.
* Iterator isPastEnd if item is not found.
*/
template <class Object>
ListItr<Object> List<Object>::find( const Object & x ) const
{
/* 1*/ int itr = cursorSpace[ header ].next;
/**
* Return iterator prior to the first node containing an item x.
*/
template <class Object>
ListItr<Object> List<Object>::findPrevious( const Object & x )
const
{
/* 1*/ int itr = header;
/**
* Remove the first occurrence of an item x.
*/
template <class Object>
void List<Object>::remove( const Object & x )
{
ListItr<Object> p = findPrevious( x );
int pos = p.current;
/**
* Deep copy of linked lists.
*/
template <class Object>
const List<Object> & List<Object>::operator=( const List<Object>
& rhs )
{
ListItr<Object> ritr = rhs.first( );
ListItr<Object> itr = zeroth( );
#include <iostream.h>
#include "CursorList.h"
int main( )
{
List<int> theList;
ListItr<int> theItr = theList.zeroth( );
int i;
printList( theList );
return 0;
}
#ifndef STACKAR_H
#define STACKAR_H
#include "vector.h"
#include "dsexceptions.h"
void makeEmpty( );
void pop( );
void push( const Object & x );
Object topAndPop( );
private:
vector<Object> theArray;
int topOfStack;
};
#include "StackAr.cpp"
#endif
StackAr.cpp: Implementation for stack: array version
#include "StackAr.h"
/**
* Construct the stack.
*/
template <class Object>
Stack<Object>::Stack( int capacity ) : theArray( capacity )
{
topOfStack = -1;
}
/**
* Test if the stack is logically empty.
* Return true if empty, false otherwise.
*/
template <class Object>
bool Stack<Object>::isEmpty( ) const
{
return topOfStack == -1;
}
/**
* Test if the stack is logically full.
* Return true if full, false otherwise.
*/
template <class Object>
bool Stack<Object>::isFull( ) const
{
return topOfStack == theArray.size( ) - 1;
}
/**
* Make the stack logically empty.
*/
template <class Object>
void Stack<Object>::makeEmpty( )
{
topOfStack = -1;
}
/**
* Get the most recently inserted item in the stack.
* Does not alter the stack.
* Return the most recently inserted item in the stack.
* Exception Underflow if stack is already empty.
*/
template <class Object>
const Object & Stack<Object>::top( ) const
{
if( isEmpty( ) )
throw Underflow( );
return theArray[ topOfStack ];
}
/**
* Remove the most recently inserted item from the stack.
* Exception Underflow if stack is already empty.
*/
template <class Object>
void Stack<Object>::pop( )
{
if( isEmpty( ) )
throw Underflow( );
topOfStack--;
}
/**
* Insert x into the stack, if not already full.
* Exception Overflow if stack is already full.
*/
template <class Object>
void Stack<Object>::push( const Object & x )
{
if( isFull( ) )
throw Overflow( );
theArray[ ++topOfStack ] = x;
}
/**
* Return and remove most recently inserted item from the stack.
* Return most recently inserted item.
* Exception Underflow if stack is already empty.
*/
template <class Object>
Object Stack<Object>::topAndPop( )
{
if( isEmpty( ) )
throw Underflow( );
return theArray[ topOfStack-- ];
}
TestStackAr.cpp: Test program for (array-based) stacks
#include <iostream.h>
#include "StackAr.h"
int main( )
{
Stack<int> s;
while( !s.isEmpty( ) )
cout << s.topAndPop( ) << endl;
return 0;
}
#ifndef STACKLI_H
#define STACKLI_H
#include "dsexceptions.h"
#include <iostream.h> // For NULL
private:
struct ListNode
{
Object element;
ListNode *next;
ListNode *topOfStack;
};
#include "StackLi.cpp"
#endif
#include "StackLi.h"
#include <iostream.h>
/**
* Construct the stack.
*/
template <class Object>
Stack<Object>::Stack( )
{
topOfStack = NULL;
}
/**
* Copy constructor.
*/
template <class Object>
Stack<Object>::Stack( const Stack<Object> & rhs )
{
topOfStack = NULL;
*this = rhs;
}
/**
* Destructor.
*/
template <class Object>
Stack<Object>::~Stack( )
{
makeEmpty( );
}
/**
* Test if the stack is logically full.
* Return false always, in this implementation.
*/
template <class Object>
bool Stack<Object>::isFull( ) const
{
return false;
}
/**
* Test if the stack is logically empty.
* Return true if empty, false otherwise.
*/
template <class Object>
bool Stack<Object>::isEmpty( ) const
{
return topOfStack == NULL;
}
/**
* Make the stack logically empty.
*/
template <class Object>
void Stack<Object>::makeEmpty( )
{
while( !isEmpty( ) )
pop( );
}
/**
* Get the most recently inserted item in the stack.
* Return the most recently inserted item in the stack
* or throw an exception if empty.
*/
template <class Object>
const Object & Stack<Object>::top( ) const
{
if( isEmpty( ) )
throw Underflow( );
return topOfStack->element;
}
/**
* Remove the most recently inserted item from the stack.
* Exception Underflow if the stack is empty.
*/
template <class Object>
void Stack<Object>::pop( )
{
if( isEmpty( ) )
throw Underflow( );
/**
* Return and remove the most recently inserted item
* from the stack.
*/
template <class Object>
Object Stack<Object>::topAndPop( )
{
Object topItem = top( );
pop( );
return topItem;
}
/**
* Insert x into the stack.
*/
template <class Object>
void Stack<Object>::push( const Object & x )
{
topOfStack = new ListNode( x, topOfStack );
}
/**
* Deep copy.
*/
template <class Object>
const Stack<Object> & Stack<Object>::
operator=( const Stack<Object> & rhs )
{
if( this != &rhs )
{
makeEmpty( );
if( rhs.isEmpty( ) )
return *this;
#include "StackLi.h"
#include <iostream.h>
int main( )
{
Stack<int> s, s1;
for( int i = 0; i < 10; i++ )
s.push( i );
s1 = s;
return 0;
}
#ifndef QUEUEAR_H
#define QUEUEAR_H
#include "vector.h"
#include "dsexceptions.h"
void makeEmpty( );
Object dequeue( );
void enqueue( const Object & x );
private:
vector<Object> theArray;
int currentSize;
int front;
int back;
#include "QueueAr.cpp"
#endif
QueueAr.cpp: Implementation for queue: array version
#include "QueueAr.h"
/**
* Construct the queue.
*/
template <class Object>
Queue<Object>::Queue( int capacity ) : theArray( capacity )
{
makeEmpty( );
}
/**
* Test if the queue is logically empty.
* Return true if empty, false otherwise.
*/
template <class Object>
bool Queue<Object>::isEmpty( ) const
{
return currentSize == 0;
}
/**
* Test if the queue is logically full.
* Return true if full, false otherwise.
*/
template <class Object>
bool Queue<Object>::isFull( ) const
{
return currentSize == theArray.size( );
}
/**
* Make the queue logically empty.
*/
template <class Object>
void Queue<Object>::makeEmpty( )
{
currentSize = 0;
front = 0;
back = -1;
}
/**
* Get the least recently inserted item in the queue.
* Return the least recently inserted item in the queue
* or throw Underflow if empty.
*/
template <class Object>
const Object & Queue<Object>::getFront( ) const
{
if( isEmpty( ) )
throw Underflow( );
return theArray[ front ];
}
/**
* Return and remove the least recently inserted item from the
queue.
* Throw Underflow if empty.
*/
template <class Object>
Object Queue<Object>::dequeue( )
{
if( isEmpty( ) )
throw Underflow( );
currentSize--;
Object frontItem = theArray[ front ];
increment( front );
return frontItem;
}
/**
* Insert x into the queue.
* Throw Overflow if queue is full
*/
template <class Object>
void Queue<Object>::enqueue( const Object & x )
{
if( isFull( ) )
throw Overflow( );
increment( back );
theArray[ back ] = x;
currentSize++;
}
/**
* Internal method to increment x with wraparound.
*/
template <class Object>
void Queue<Object>::increment( int & x )
{
if( ++x == theArray.size( ) )
x = 0;
}
TestQueueAr.cpp: Test program for queues
#include <iostream.h>
#include "QueueAr.h"
int main( )
{
Queue<int> q;
while( !q.isEmpty( ) )
cout << q.dequeue( ) << endl;
}
return 0;
}
BinarySearchTree.h: Header file for binary search tree
#ifndef BINARY_SEARCH_TREE_H_
#define BINARY_SEARCH_TREE_H_
#include "dsexceptions.h"
#include <iostream.h> // For NULL
// BinarySearchTree class
//
// CONSTRUCTION: with ITEM_NOT_FOUND object used to signal
failed finds
//
// ******************PUBLIC OPERATIONS*********************
// void insert( x ) --> Insert x
// void remove( x ) --> Remove x
// Comparable find( x ) --> Return item that matches x
// Comparable findMin( ) --> Return smallest item
// Comparable findMax( ) --> Return largest item
// boolean isEmpty( ) --> Return true if empty; else false
// void makeEmpty( ) --> Remove all items
// void printTree( ) --> Print tree in sorted order
template <class Comparable>
class BinarySearchTree
{
public:
explicit BinarySearchTree( const Comparable & notFound );
BinarySearchTree( const BinarySearchTree & rhs );
~BinarySearchTree( );
void makeEmpty( );
void insert( const Comparable & x );
void remove( const Comparable & x );
private:
BinaryNode<Comparable> *root;
const Comparable ITEM_NOT_FOUND;
#include "BinarySearchTree.cpp"
#endif
BinarySearchTree.cpp: Implementation for binary search tree
#include "BinarySearchTree.h"
#include <iostream.h>
/**
* Implements an unbalanced binary search tree.
* Note that all "matching" is based on the < method.
*/
/**
* Construct the tree.
*/
template <class Comparable>
BinarySearchTree<Comparable>::BinarySearchTree( const Comparable
& notFound ) :
root( NULL ), ITEM_NOT_FOUND( notFound )
{
}
/**
* Copy constructor.
*/
template <class Comparable>
BinarySearchTree<Comparable>::
BinarySearchTree( const BinarySearchTree<Comparable> & rhs ) :
root( NULL ), ITEM_NOT_FOUND( rhs.ITEM_NOT_FOUND )
{
*this = rhs;
}
/**
* Destructor for the tree.
*/
template <class Comparable>
BinarySearchTree<Comparable>::~BinarySearchTree( )
{
makeEmpty( );
}
/**
* Insert x into the tree; duplicates are ignored.
*/
template <class Comparable>
void BinarySearchTree<Comparable>::insert( const Comparable &
x )
{
insert( x, root );
}
/**
* Remove x from the tree. Nothing is done if x is not found.
*/
template <class Comparable>
void BinarySearchTree<Comparable>::remove( const Comparable &
x )
{
remove( x, root );
}
/**
* Find the smallest item in the tree.
* Return smallest item or ITEM_NOT_FOUND if empty.
*/
template <class Comparable>
const Comparable & BinarySearchTree<Comparable>::findMin( )
const
{
return elementAt( findMin( root ) );
}
/**
* Find the largest item in the tree.
* Return the largest item of ITEM_NOT_FOUND if empty.
*/
template <class Comparable>
const Comparable & BinarySearchTree<Comparable>::findMax( )
const
{
return elementAt( findMax( root ) );
}
/**
* Find item x in the tree.
* Return the matching item or ITEM_NOT_FOUND if not found.
*/
template <class Comparable>
const Comparable & BinarySearchTree<Comparable>::
find( const Comparable & x ) const
{
return elementAt( find( x, root ) );
}
/**
* Make the tree logically empty.
*/
template <class Comparable>
void BinarySearchTree<Comparable>::makeEmpty( )
{
makeEmpty( root );
}
/**
* Test if the tree is logically empty.
* Return true if empty, false otherwise.
*/
template <class Comparable>
bool BinarySearchTree<Comparable>::isEmpty( ) const
{
return root == NULL;
}
/**
* Print the tree contents in sorted order.
*/
template <class Comparable>
void BinarySearchTree<Comparable>::printTree( ) const
{
if( isEmpty( ) )
cout << "Empty tree" << endl;
else
printTree( root );
}
/**
* Deep copy.
*/
template <class Comparable>
const BinarySearchTree<Comparable> &
BinarySearchTree<Comparable>::
operator=( const BinarySearchTree<Comparable> & rhs )
{
if( this != &rhs )
{
makeEmpty( );
root = clone( rhs.root );
}
return *this;
}
/**
* Internal method to get element field in node t.
* Return the element field or ITEM_NOT_FOUND if t is NULL.
*/
template <class Comparable>
const Comparable & BinarySearchTree<Comparable>::
elementAt( BinaryNode<Comparable> *t ) const
{
if( t == NULL )
return ITEM_NOT_FOUND;
else
return t->element;
}
/**
* Internal method to insert into a subtree.
* x is the item to insert.
* t is the node that roots the tree.
* Set the new root.
*/
template <class Comparable>
void BinarySearchTree<Comparable>::
insert( const Comparable & x, BinaryNode<Comparable> * & t )
const
{
if( t == NULL )
t = new BinaryNode<Comparable>( x, NULL, NULL );
else if( x < t->element )
insert( x, t->left );
else if( t->element < x )
insert( x, t->right );
else
; // Duplicate; do nothing
}
/**
* Internal method to remove from a subtree.
* x is the item to remove.
* t is the node that roots the tree.
* Set the new root.
*/
template <class Comparable>
void BinarySearchTree<Comparable>::
remove( const Comparable & x, BinaryNode<Comparable> * & t )
const
{
if( t == NULL )
return; // Item not found; do nothing
if( x < t->element )
remove( x, t->left );
else if( t->element < x )
remove( x, t->right );
else if( t->left != NULL && t->right != NULL ) // Two
children
{
t->element = findMin( t->right )->element;
remove( t->element, t->right );
}
else
{
BinaryNode<Comparable> *oldNode = t;
t = ( t->left != NULL ) ? t->left : t->right;
delete oldNode;
}
}
/**
* Internal method to find the smallest item in a subtree t.
* Return node containing the smallest item.
*/
template <class Comparable>
BinaryNode<Comparable> *
BinarySearchTree<Comparable>::findMin( BinaryNode<Comparable> *t
) const
{
if( t == NULL )
return NULL;
if( t->left == NULL )
return t;
return findMin( t->left );
}
/**
* Internal method to find the largest item in a subtree t.
* Return node containing the largest item.
*/
template <class Comparable>
BinaryNode<Comparable> *
BinarySearchTree<Comparable>::findMax( BinaryNode<Comparable> *t
) const
{
if( t != NULL )
while( t->right != NULL )
t = t->right;
return t;
}
/**
* Internal method to find an item in a subtree.
* x is item to search for.
* t is the node that roots the tree.
* Return node containing the matched item.
*/
template <class Comparable>
BinaryNode<Comparable> *
BinarySearchTree<Comparable>::
find( const Comparable & x, BinaryNode<Comparable> *t ) const
{
if( t == NULL )
return NULL;
else if( x < t->element )
return find( x, t->left );
else if( t->element < x )
return find( x, t->right );
else
return t; // Match
}
/****** NONRECURSIVE VERSION*************************
template <class Comparable>
BinaryNode<Comparable> *
BinarySearchTree<Comparable>::
find( const Comparable & x, BinaryNode<Comparable> *t ) const
{
while( t != NULL )
if( x < t->element )
t = t->left;
else if( t->element < x )
t = t->right;
else
return t; // Match
/**
* Internal method to make subtree empty.
*/
template <class Comparable>
void BinarySearchTree<Comparable>::
makeEmpty( BinaryNode<Comparable> * & t ) const
{
if( t != NULL )
{
makeEmpty( t->left );
makeEmpty( t->right );
delete t;
}
t = NULL;
}
/**
* Internal method to print a subtree rooted at t in sorted
order.
*/
template <class Comparable>
void
BinarySearchTree<Comparable>::printTree( BinaryNode<Comparable> *t )
const
{
if( t != NULL )
{
printTree( t->left );
cout << t->element << endl;
printTree( t->right );
}
}
/**
* Internal method to clone subtree.
*/
template <class Comparable>
BinaryNode<Comparable> *
BinarySearchTree<Comparable>::clone( BinaryNode<Comparable> *
t ) const
{
if( t == NULL )
return NULL;
else
return new BinaryNode<Comparable>( t->element, clone( t-
>left ), clone( t->right ) );
}
TestBinarySearchTree.cpp: Test program for binary search tree
#include <iostream.h>
#include "BinarySearchTree.h"
// Test program
int main( )
{
const int ITEM_NOT_FOUND = -9999;
BinarySearchTree<int> t( ITEM_NOT_FOUND );
int NUMS = 4000;
const int GAP = 37;
int i;
return 0;
}
AvlTree.h: Header file for AVL tree
#ifndef AVL_TREE_H_
#define AVL_TREE_H_
#include "dsexceptions.h"
#include <iostream.h> // For NULL
// AvlTree class
//
// CONSTRUCTION: with ITEM_NOT_FOUND object used to signal
failed finds
//
// ******************PUBLIC OPERATIONS*********************
// void insert( x ) --> Insert x
// void remove( x ) --> Remove x (unimplemented)
// Comparable find( x ) --> Return item that matches x
// Comparable findMin( ) --> Return smallest item
// Comparable findMax( ) --> Return largest item
// boolean isEmpty( ) --> Return true if empty; else false
// void makeEmpty( ) --> Remove all items
// void printTree( ) --> Print tree in sorted order
void makeEmpty( );
void insert( const Comparable & x );
void remove( const Comparable & x );
private:
AvlNode<Comparable> *root;
const Comparable ITEM_NOT_FOUND;
// Avl manipulations
int height( AvlNode<Comparable> *t ) const;
int max( int lhs, int rhs ) const;
void rotateWithLeftChild( AvlNode<Comparable> * & k2 )
const;
void rotateWithRightChild( AvlNode<Comparable> * & k1 )
const;
void doubleWithLeftChild( AvlNode<Comparable> * & k3 )
const;
void doubleWithRightChild( AvlNode<Comparable> * & k1 )
const;
};
#include "AvlTree.cpp"
#endif
AvlTree.cpp: Implementation for AVL tree
#include "AvlTree.h"
#include <iostream.h>
/**
* Implements an unbalanced Avl search tree.
* Note that all "matching" is based on the compares method.
* @author Mark Allen Weiss
*/
/**
* Construct the tree.
*/
template <class Comparable>
AvlTree<Comparable>::AvlTree( const Comparable & notFound ) :
ITEM_NOT_FOUND( notFound ), root( NULL )
{
}
/**
* Copy constructor.
*/
template <class Comparable>
AvlTree<Comparable>::AvlTree( const AvlTree<Comparable> &
rhs ) :
ITEM_NOT_FOUND( rhs.ITEM_NOT_FOUND ), root( NULL )
{
*this = rhs;
}
/**
* Destructor for the tree.
*/
template <class Comparable>
AvlTree<Comparable>::~AvlTree( )
{
makeEmpty( );
}
/**
* Insert x into the tree; duplicates are ignored.
*/
template <class Comparable>
void AvlTree<Comparable>::insert( const Comparable & x )
{
insert( x, root );
}
/**
* Remove x from the tree. Nothing is done if x is not found.
*/
template <class Comparable>
void AvlTree<Comparable>::remove( const Comparable & x )
{
cout << "Sorry, remove unimplemented; " << x <<
" still present" << endl;
}
/**
* Find the smallest item in the tree.
* Return smallest item or ITEM_NOT_FOUND if empty.
*/
template <class Comparable>
const Comparable & AvlTree<Comparable>::findMin( ) const
{
return elementAt( findMin( root ) );
}
/**
* Find the largest item in the tree.
* Return the largest item of ITEM_NOT_FOUND if empty.
*/
template <class Comparable>
const Comparable & AvlTree<Comparable>::findMax( ) const
{
return elementAt( findMax( root ) );
}
/**
* Find item x in the tree.
* Return the matching item or ITEM_NOT_FOUND if not found.
*/
template <class Comparable>
const Comparable & AvlTree<Comparable>::
find( const Comparable & x ) const
{
return elementAt( find( x, root ) );
}
/**
* Make the tree logically empty.
*/
template <class Comparable>
void AvlTree<Comparable>::makeEmpty( )
{
makeEmpty( root );
}
/**
* Test if the tree is logically empty.
* Return true if empty, false otherwise.
*/
template <class Comparable>
bool AvlTree<Comparable>::isEmpty( ) const
{
return root == NULL;
}
/**
* Print the tree contents in sorted order.
*/
template <class Comparable>
void AvlTree<Comparable>::printTree( ) const
{
if( isEmpty( ) )
cout << "Empty tree" << endl;
else
printTree( root );
}
/**
* Deep copy.
*/
template <class Comparable>
const AvlTree<Comparable> &
AvlTree<Comparable>::
operator=( const AvlTree<Comparable> & rhs )
{
if( this != &rhs )
{
makeEmpty( );
root = clone( rhs.root );
}
return *this;
}
/**
* Internal method to get element field in node t.
* Return the element field or ITEM_NOT_FOUND if t is NULL.
*/
template <class Comparable>
const Comparable &
AvlTree<Comparable>::elementAt( AvlNode<Comparable> *t ) const
{
if( t == NULL )
return ITEM_NOT_FOUND;
else
return t->element;
}
/**
* Internal method to insert into a subtree.
* x is the item to insert.
* t is the node that roots the tree.
*/
template <class Comparable>
void AvlTree<Comparable>::insert( const Comparable & x,
AvlNode<Comparable> * & t ) const
{
if( t == NULL )
t = new AvlNode<Comparable>( 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
; // Duplicate; do nothing
t->height = max( height( t->left ), height( t->right ) ) +
1;
}
/**
* Internal method to find the smallest item in a subtree t.
* Return node containing the smallest item.
*/
template <class Comparable>
AvlNode<Comparable> *
AvlTree<Comparable>::findMin( AvlNode<Comparable> *t ) const
{
if( t == NULL)
return t;
/**
* Internal method to find the largest item in a subtree t.
* Return node containing the largest item.
*/
template <class Comparable>
AvlNode<Comparable> *
AvlTree<Comparable>::findMax( AvlNode<Comparable> *t ) const
{
if( t == NULL )
return t;
/**
* Internal method to find an item in a subtree.
* x is item to search for.
* t is the node that roots the tree.
* Return node containing the matched item.
*/
template <class Comparable>
AvlNode<Comparable> *
AvlTree<Comparable>::find( const Comparable & x,
AvlNode<Comparable> *t ) const
{
while( t != NULL )
if( x < t->element )
t = t->left;
else if( t->element < x )
t = t->right;
else
return t; // Match
/**
* Internal method to make subtree empty.
*/
template <class Comparable>
void AvlTree<Comparable>::makeEmpty( AvlNode<Comparable> * & t )
const
{
if( t != NULL )
{
makeEmpty( t->left );
makeEmpty( t->right );
delete t;
}
t = NULL;
}
/**
* Internal method to clone subtree.
*/
template <class Comparable>
AvlNode<Comparable> *
AvlTree<Comparable>::clone( AvlNode<Comparable> * t ) const
{
if( t == NULL )
return NULL;
else
return new AvlNode<Comparable>( t->element, clone( t-
>left ),
clone( t->right ), t-
>height );
}
/**
* Return the height of node t or -1 if NULL.
*/
template <class Comparable>
int AvlTree<Comparable>::height( AvlNode<Comparable> *t ) const
{
return t == NULL ? -1 : t->height;
}
/**
* Return maximum of lhs and rhs.
*/
template <class Comparable>
int AvlTree<Comparable>::max( int lhs, int rhs ) const
{
return lhs > rhs ? lhs : rhs;
}
/**
* Rotate binary tree node with left child.
* For AVL trees, this is a single rotation for case 1.
* Update heights, then set new root.
*/
template <class Comparable>
void
AvlTree<Comparable>::rotateWithLeftChild( AvlNode<Comparable> * & k2 )
const
{
AvlNode<Comparable> *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;
}
/**
* Rotate binary tree node with right child.
* For AVL trees, this is a single rotation for case 4.
* Update heights, then set new root.
*/
template <class Comparable>
void
AvlTree<Comparable>::rotateWithRightChild( AvlNode<Comparable> * & k1 )
const
{
AvlNode<Comparable> *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;
}
/**
* Double rotate binary tree node: first left child.
* with its right child; then node k3 with new left child.
* For AVL trees, this is a double rotation for case 2.
* Update heights, then set new root.
*/
template <class Comparable>
void
AvlTree<Comparable>::doubleWithLeftChild( AvlNode<Comparable> * & k3 )
const
{
rotateWithRightChild( k3->left );
rotateWithLeftChild( k3 );
}
/**
* Double rotate binary tree node: first right child.
* with its left child; then node k1 with new right child.
* For AVL trees, this is a double rotation for case 3.
* Update heights, then set new root.
*/
template <class Comparable>
void
AvlTree<Comparable>::doubleWithRightChild( AvlNode<Comparable> * & k1 )
const
{
rotateWithLeftChild( k1->right );
rotateWithRightChild( k1 );
}
/**
* Internal method to print a subtree in sorted order.
* t points to the node that roots the tree.
*/
template <class Comparable>
void AvlTree<Comparable>::printTree( AvlNode<Comparable> *t )
const
{
if( t != NULL )
{
printTree( t->left );
cout << t->element << endl;
printTree( t->right );
}
}
#include <iostream.h>
#include "AvlTree.h"
// Test program
int main( )
{
const int ITEM_NOT_FOUND = -9999;
AvlTree<int> t( ITEM_NOT_FOUND ), t2( ITEM_NOT_FOUND );
int NUMS = 40000;
const int GAP = 37;
int i;
t2 = t;
return 0;
}
Source Code for Data Structures and
Algorithm Analysis in C++ (Second
Edition)
Here is the source code for Data Structures and Algorithm Analysis in C++ (Second
Edition), by Mark Allen Weiss. The materials here are copyrighted.
I have successfully compiled and tested the programs under Borland 5.0, Visual C+
+ 5.0 and 6.0, CodeWarrior Pro Release 2 (Windows), g++ 2.7.2 and 2.8.1, and
SunPro 4.1. Greg Ozbirn from U.T. Dallas has rewritten the code using ANSI C++.
This mostly involves fixing the header files. Click here to obtain the ANSI C++
conversion
Known Bugs
TestCursorList.cpp does not compile under g++ 2.7.2. I think it is a problem
with static template members, which g++ does not understand until g++ 2.8.1.
Metrowerks insists on compiling the STL, which causes conflicts for swap and
merge in Sort.h. Also, it does not understand default template parameters,
making its vector and string incompatible with some of the code. The easy fix
is to add preprocessor macros as follows: in vector.h, #define vector
Vector; similarly for string.h and in Sort.h. This works as long as
iostream.h is included prior to the other header files, as is done in the online
code.
Compilation Instructions
Here are compilation instructions for g++, SunPro, Borland 5.0, and Visual 5.0. (How to
setup Windows for Visual command line compilation.) You can use this to guide you on
how to generate project files for Visual C++. Throughout I am assuming 32-bit ints. All
template classes have the header file include the .cpp file, even though this defeats the
purpose of separate compilation. There are ways around this, but I'd rather keep
everything simple for now. Jeffrey Walton has supplied some common workarounds for
C++ compilers. Finally, here is a zip file that contains CodeWarrior projects. You'll have
to get everything in the correct directories. (Does not include some late additions from
Chapter 1; check back later).
Complete Bundle
Unix tar | gzip
Unix tar (Winzip can read this.)
Note to Macintosh users: There is a utility to read zip files. Click here to
download.
Individual Files
mystring.h: If you don't have a string type
Polynomial.cpp: Polynomials