I got the following code out of Carrano's Walls & Mirrors. I made a few changes but have tested it and it works. I'm really confused by line 19 in the .h file. Why is it structured like "void (*FunctionType)"?
Why not (void*) FunctionType?
or void* FunctionType?
What is the significance of the parenthesis being around the *FunctionType? I've tried changing this and it only works if I leave it the way it is.
Thanks
Jake
/********************************************************************************************************************************
* @file: BinaryTree.h
* @purpose: Specification for the binary tree to be used for representing math equations (from Carrano's implementation
* in Walls & Mirrors Fifth Edition)
* @author: Frank M. Carrano
* @date: 10/1/09
*******************************************************************************************************************************/
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include "KeyedItem.h"
#include "TreeException.h"
#include "TreeNode.h"
#include <cstddef> // definition of NULL
#include <new>
#include <iostream>
using namespace std;
typedef void (*FunctionType)(TreeNode* curNode); // the function to be called during inorder traversal
/*******************************************************************************************************************************
* @class: BinaryTree
* @purpose: Implementation of a binary tree to be used in expressing math equations
*******************************************************************************************************************************/
class BinaryTree {
public:
BinaryTree();
BinaryTree(const TreeItemType& rootItem) throw(TreeException);
BinaryTree(const TreeItemType& rootItem, BinaryTree& leftTree, BinaryTree& rightTree) throw(TreeException);
BinaryTree(BinaryTree& tree) throw(TreeException);
virtual ~BinaryTree();
virtual bool isEmpty() const;
virtual TreeItemType getRootData() const throw(TreeException);
virtual void setRootData(const TreeItemType& newItem) throw(TreeException);
virtual TreeNode* attachLeft(const TreeItemType& newItem) throw(TreeException);
virtual TreeNode* attachRight(const TreeItemType& newItem) throw(TreeException);
virtual void attachLeftSubtree(BinaryTree& leftTree) throw(TreeException);
virtual void attachRightSubtree(BinaryTree& rightTree) throw(TreeException);
virtual void detachLeftSubtree(BinaryTree& leftTree) throw(TreeException);
virtual void detachRightSubtree(BinaryTree& rightTree) throw(TreeException);
virtual BinaryTree getLeftSubtree() const throw(TreeException);
virtual BinaryTree getRightSubtree() const throw(TreeException);
virtual BinaryTree& operator=(const BinaryTree& rhs) throw(TreeException);
/********************************************************************************************************************************
* @purpose: public method that calls the protected method inOrder, to display every node in the tree in in-order representation
* @param: pointer to the function that will visit each node
*******************************************************************************************************************************/
virtual void inOrderTraverse(FunctionType visit);
virtual void preOrderTraverse(FunctionType visit);
TreeNode *rootPtr() const;
protected:
BinaryTree(TreeNode *nodePtr);
void copyTree(TreeNode *treePtr, TreeNode *& newTreePtr) const throw(TreeException);
/********************************************************************************************************************************
* @purpose: Deallocates memory used by tree and deletes the tree
* @param: Pointer to the tree in question
*******************************************************************************************************************************/
void destroyTree(TreeNode* treePtr) throw(TreeException);
void inOrder(TreeNode *nodePtr, FunctionType visit); // this is protected because it has access to every node in the tree
void preOrder(TreeNode *nodePtr, FunctionType visit);
void setRootPtr(TreeNode *newRoot);
void getChildPtrs(TreeNode *nodePtr, TreeNode *& leftChildPtr, TreeNode *& rightChildPtr) const;
void setChildPtrs(TreeNode *nodePtr, TreeNode *leftChildPtr, TreeNode *rightChildPtr);
TreeNode *root; // Pointer to the root of the tree
};
#endif
/********************************************************************************************************************************
* @file: BinaryTree.cpp
* @purpose: Implementation for the binary tree to be used for representing math equations (from Carrano's implementation
* in Walls & Mirrors Fifth Edition)
* @author: Frank M. Carrano
* @date: 10/2/09
*******************************************************************************************************************************/
#include "BinaryTree.h"
BinaryTree::BinaryTree() : root(NULL){
}
BinaryTree::BinaryTree(const TreeItemType& rootItem) throw(TreeException)
{
try{
root = new TreeNode(rootItem, NULL, NULL);
}
catch(bad_alloc e){
delete root;
throw TreeException("TreeException: constructor cannot allocate memory");
}
}
BinaryTree::BinaryTree(const TreeItemType& rootItem, BinaryTree& leftTree, BinaryTree& rightTree) throw(TreeException){
try{
root = new TreeNode(rootItem, NULL, NULL);
attachLeftSubtree(leftTree);
attachRightSubtree(rightTree);
}
catch(bad_alloc e){
delete root;
throw TreeException("TreeException: constructor cannot allocate memory");
}
}
BinaryTree::BinaryTree(BinaryTree& tree) throw(TreeException){
try{
copyTree(tree.root, root);
}
catch(bad_alloc e){
destroyTree(tree.root);
throw TreeException("TreeException: copy constructor cannot allocate memory");
}
}
BinaryTree::BinaryTree(TreeNode *nodePtr) : root(nodePtr){
}
BinaryTree::~BinaryTree(){
destroyTree(root);
root = NULL;
}
bool BinaryTree::isEmpty() const{
return(root == NULL);
}
TreeItemType BinaryTree::getRootData() const throw(TreeException){
if(isEmpty())
throw TreeException("TreeException: Empty tree");
return root->item;
}
void BinaryTree::setRootData(const TreeItemType& newItem) throw(TreeException){
if(!isEmpty()){
root->item = newItem;
}
else{
try{
root = new TreeNode(newItem, NULL, NULL);
}
catch(bad_alloc e){
throw TreeException("TreeException: setRootData cannot allocate memory");
}
}
}
TreeNode* BinaryTree::attachLeft(const TreeItemType& newItem) throw(TreeException){
if(isEmpty())
throw TreeException("TreeException: Empty tree");
else if(root->leftChildPtr != NULL)
throw TreeException("TreeException: Cannot overwrite left subtree");
else{
try{
root->leftChildPtr = new TreeNode(newItem, NULL, NULL);
return root->leftChildPtr;
}
catch(bad_alloc e){
throw TreeException("TreeException: attachLeft cannot allocate memory");
}
}
}
TreeNode* BinaryTree::attachRight(const TreeItemType& newItem) throw(TreeException){
if(isEmpty())
throw TreeException("TreeException: Empty tree");
else if(root->rightChildPtr != NULL)
throw TreeException("TreeException: Cannot overwrite right subtree");
else{
try{
root->rightChildPtr = new TreeNode(newItem, NULL, NULL);
return root->rightChildPtr;
}
catch(bad_alloc e){
throw TreeException("TreeException: attachRight cannot allocate memory");
}
}
}
void BinaryTree::attachLeftSubtree(BinaryTree& leftTree) throw(TreeException){
if(isEmpty())
throw TreeException("TreeException: Empty tree");
else if(root->leftChildPtr != NULL)
throw TreeException("TreeException: Cannot overwrite left subtree");
else{
root->leftChildPtr = leftTree.root;
leftTree.root = NULL;
}
}
void BinaryTree::attachRightSubtree(BinaryTree& rightTree) throw(TreeException){
if(isEmpty())
throw TreeException("TreeException: Empty tree");
else if(root->rightChildPtr != NULL)
throw TreeException("TreeException: Cannot overwrite right subtree");
else{
root->rightChildPtr = rightTree.root;
rightTree.root = NULL;
}
}
void BinaryTree::detachLeftSubtree(BinaryTree& leftTree) throw(TreeException){
if(isEmpty())
throw TreeException("TreeException: Empty tree");
else{
leftTree = BinaryTree(root->leftChildPtr);
root->leftChildPtr = NULL;
}
}
void BinaryTree::detachRightSubtree(BinaryTree& rightTree) throw(TreeException){
if(isEmpty())
throw TreeException("TreeException: Empty tree");
else{
rightTree = BinaryTree(root->rightChildPtr);
root->rightChildPtr = NULL;
}
}
BinaryTree BinaryTree::getLeftSubtree() const throw(TreeException){
TreeNode *subTreePtr;
if(isEmpty()){
BinaryTree emptyTree;
return emptyTree;
}
else{
copyTree(root->leftChildPtr, subTreePtr);
BinaryTree leftTree(subTreePtr);
return leftTree;
}
}
BinaryTree BinaryTree::getRightSubtree() const throw(TreeException){
TreeNode *subTreePtr;
if(isEmpty()){
BinaryTree emptyTree;
return emptyTree;
}
else{
copyTree(root->rightChildPtr, subTreePtr);
BinaryTree rightTree(subTreePtr);
return rightTree;
}
}
BinaryTree& BinaryTree::operator=(const BinaryTree& rhs) throw(TreeException){
if(this != &rhs){
destroyTree(root);
copyTree(rhs.root, root);
}
return *this;
}
void BinaryTree::copyTree(TreeNode *treePtr, TreeNode *& newTreePtr) const throw(TreeException){
if(treePtr != NULL){
try{
newTreePtr = new TreeNode(treePtr->item, NULL, NULL);
copyTree(treePtr->leftChildPtr, newTreePtr->leftChildPtr);
copyTree(treePtr->rightChildPtr, newTreePtr->rightChildPtr);
}
catch(bad_alloc e){
throw TreeException("TreeException: copyTree cannot allocate memory");
}
}
else
newTreePtr = NULL;
}
void BinaryTree::destroyTree(TreeNode* treePtr) throw(TreeException){
if(treePtr != NULL){
destroyTree(treePtr->leftChildPtr);
destroyTree(treePtr->rightChildPtr);
delete treePtr;
treePtr = NULL;
if(treePtr == root) { // get rid of the root
delete root;
root = NULL;
}
}
}
TreeNode *BinaryTree::rootPtr() const {
return root;
}
void BinaryTree::setRootPtr(TreeNode *newRoot){
root = newRoot;
}
void BinaryTree::getChildPtrs(TreeNode *nodePtr, TreeNode *& leftPtr, TreeNode *& rightPtr) const {
leftPtr = nodePtr->leftChildPtr;
rightPtr = nodePtr->rightChildPtr;
}
void BinaryTree::setChildPtrs(TreeNode *nodePtr, TreeNode * leftPtr, TreeNode * rightPtr) {
nodePtr->leftChildPtr = leftPtr;
nodePtr->rightChildPtr = rightPtr;
}
void BinaryTree::inOrderTraverse(FunctionType visit){
inOrder(root, visit);
}
void BinaryTree::inOrder(TreeNode* nodePtr, FunctionType visit) {
if(nodePtr != NULL){
inOrder(nodePtr->leftChildPtr, visit);
visit(nodePtr);
inOrder(nodePtr->rightChildPtr, visit);
}
}
void BinaryTree::preOrderTraverse(FunctionType visit) {
preOrder(root, visit);
}
void BinaryTree::preOrder(TreeNode* nodePtr, FunctionType visit) {
if(nodePtr != NULL) {
visit(nodePtr);
preOrder(nodePtr->leftChildPtr, visit);
preOrder(nodePtr->rightChildPtr, visit);
}
}