text cover

Data Abstraction and Problem Solving with C++

Walls and Mirrors

by Frank M. Carrano

Addison Wesley Logo

BST.cpp

Go to the documentation of this file.
00001 
00016 #include <cstddef>   // definition of NULL
00017 #include <new>       // for bad_alloc
00018 #include "BST.h"     // header file
00019 
00020 using namespace std;
00021 
00022 BinarySearchTree::BinarySearchTree() : root(NULL)
00023 {
00024 }  // end default constructor
00025 
00026 BinarySearchTree::BinarySearchTree(const BinarySearchTree& tree)
00027    throw(TreeException)
00028 {
00029    copyTree(tree.root, root);
00030 }  // end copy constructor
00031 
00032 BinarySearchTree::~BinarySearchTree()
00033 {
00034    destroyTree(root);
00035 }  // end destructor
00036 
00037 bool BinarySearchTree::isEmpty() const
00038 {
00039    return (root == NULL);
00040 }  // end searchTreeIsEmpty
00041 
00042 void BinarySearchTree::searchTreeInsert(const TreeItemType& newItem)
00043    throw(TreeException)
00044 {
00045    insertItem(root, newItem);
00046 }  // end searchTreeInsert
00047 
00048 void BinarySearchTree::searchTreeDelete(KeyType searchKey)
00049    throw(TreeException)
00050 {
00051    deleteItem(root, searchKey);
00052 }  // end searchTreeDelete
00053 
00054 void BinarySearchTree::searchTreeRetrieve(KeyType searchKey,
00055                  TreeItemType& treeItem) const
00056    throw(TreeException)
00057 {
00058    // if retrieveItem throws a TreeException, it is
00059    // ignored here and passed on to the point in the code
00060    // where searchTreeRetrieve was called
00061    retrieveItem(root, searchKey, treeItem);
00062 }  // end searchTreeRetrieve
00063 
00064 void BinarySearchTree::preorderTraverse(FunctionType visit)
00065 {
00066    preorder(root, visit);
00067 }  // end preorderTraverse
00068 
00069 void BinarySearchTree::inorderTraverse(FunctionType visit)
00070 {
00071    inorder(root, visit);
00072 }  // end inorderTraverse
00073 
00074 void BinarySearchTree::postorderTraverse(FunctionType visit)
00075 {
00076    postorder(root, visit);
00077 }  // end postorderTraverse
00078 
00079 void BinarySearchTree::insertItem(TreeNode *& treePtr,
00080               const TreeItemType& newItem)
00081    throw(TreeException)
00082 {
00083    if (treePtr == NULL)
00084    {  // position of insertion found; insert after leaf
00085 
00086       // create a new node
00087       try
00088       {
00089     treePtr = new TreeNode(newItem, NULL, NULL);
00090       }
00091       catch (bad_alloc e)
00092       {
00093     throw TreeException(
00094     "TreeException: insertItem cannot allocate memory");
00095       }  // end try
00096    }
00097    // else search for the insertion position
00098    else if (newItem.getKey() < treePtr->item.getKey())
00099       // search the left subtree
00100       insertItem(treePtr->leftChildPtr, newItem);
00101 
00102    else  // search the right subtree
00103       insertItem(treePtr->rightChildPtr, newItem);
00104 }  // end insertItem
00105 
00106 void BinarySearchTree::deleteItem(TreeNode *& treePtr,
00107                                   KeyType searchKey)
00108    throw(TreeException)
00109 // Calls: deleteNodeItem.
00110 {
00111    if (treePtr == NULL)
00112       throw TreeException("TreeException: delete failed");  // empty tree
00113 
00114    else if (searchKey == treePtr->item.getKey())
00115       // item is in the root of some subtree
00116       deleteNodeItem(treePtr);  // delete the item
00117 
00118    // else search for the item
00119    else if (searchKey < treePtr->item.getKey())
00120       // search the left subtree
00121       deleteItem(treePtr->leftChildPtr, searchKey);
00122 
00123    else  // search the right subtree
00124       deleteItem(treePtr->rightChildPtr, searchKey);
00125 }  // end deleteItem
00126 
00127 void BinarySearchTree::deleteNodeItem(TreeNode *& nodePtr)
00128 // Algorithm note: There are four cases to consider:
00129 //   1. The root is a leaf.
00130 //   2. The root has no left child.
00131 //   3. The root has no right child.
00132 //   4. The root has two children.
00133 // Calls: processLeftmost.
00134 {
00135    TreeNode     *delPtr;
00136    TreeItemType replacementItem;
00137 
00138    // test for a leaf
00139    if ( (nodePtr->leftChildPtr == NULL) &&
00140         (nodePtr->rightChildPtr == NULL) )
00141    {  delete nodePtr;
00142       nodePtr = NULL;
00143    }  // end if leaf
00144    // test for no left child
00145    else if (nodePtr->leftChildPtr == NULL)
00146    {  delPtr = nodePtr;
00147       nodePtr = nodePtr->rightChildPtr;
00148       delPtr->rightChildPtr = NULL;
00149       delete delPtr;
00150    }  // end if no left child
00151 
00152    // test for no right child
00153    else if (nodePtr->rightChildPtr == NULL)
00154    {  delPtr = nodePtr;
00155       nodePtr = nodePtr->leftChildPtr;
00156       delPtr->leftChildPtr = NULL;
00157       delete delPtr;
00158    }  // end if no right child
00159 
00160    // there are two children:
00161    // retrieve and delete the inorder successor
00162    else
00163    {  processLeftmost(nodePtr->rightChildPtr,
00164                       replacementItem);
00165       nodePtr->item = replacementItem;
00166    }  // end if two children
00167 }  // end deleteNodeItem
00168 
00169 void BinarySearchTree::processLeftmost(TreeNode *& nodePtr, TreeItemType& treeItem)
00170 {
00171    if (nodePtr->leftChildPtr == NULL)
00172    {  treeItem = nodePtr->item;
00173       TreeNode *delPtr = nodePtr;
00174       nodePtr = nodePtr->rightChildPtr;
00175       delPtr->rightChildPtr = NULL;  // defense
00176       delete delPtr;
00177    }
00178 
00179    else
00180       processLeftmost(nodePtr->leftChildPtr, treeItem);
00181 }  // end processLeftmost
00182 
00183 void BinarySearchTree::retrieveItem(TreeNode *treePtr,
00184                                     KeyType searchKey,
00185                                     TreeItemType& treeItem) const
00186    throw(TreeException)
00187 {
00188    if (treePtr == NULL)
00189       throw TreeException("TreeException: searchKey not found");
00190 
00191    else if (searchKey == treePtr->item.getKey())
00192       // item is in the root of some subtree
00193       treeItem = treePtr->item;
00194 
00195    else if (searchKey < treePtr->item.getKey())
00196       // search the left subtree
00197       retrieveItem(treePtr->leftChildPtr,
00198                    searchKey, treeItem);
00199 
00200    else  // search the right subtree
00201       retrieveItem(treePtr->rightChildPtr,
00202                           searchKey, treeItem);
00203 }  // end retrieveItem
00204 
00205 // Implementations of copyTree, destroyTree, preorder,
00206 // inorder, postorder, setRootPtr, rootPtr, getChildPtrs,
00207 // setChildPtrs, and the overloaded assignment operator are
00208 // the same as for the ADT binary tree.
00209 // End of implementation file.

Generated on Sun Aug 27 22:04:06 2006 for AWLogo by  doxygen 1.4.6