i don\'t think you guys need to copy all the classes but i\'ve provided them jus
ID: 3828078 • Letter: I
Question
i don't think you guys need to copy all the classes but i've provided them just in case.
Project 3B : Working With Binary Tree Representation
Complete the following exercises using the cs20::BinaryTree class presented in class.
1. Implement a PreOrder, InOrder or PostOrder BinaryTreeIterator using the BinaryTreeIterator class as the base class of the class you create.
2. Without using a BinaryTreeIterator, create a new method called isProperDescendant that takes two Objects and returns true when the second parameter is a proper descendant of the first parameter. Recall that for a proper descendant to exist, the path of nodes between the first parameter and the second parameter in the tree cannot be the zero-length path. If either parameter is not found in the tree, your method should throw the InvalidTreeArgument exception.
HINT: Don't quit early. Just because you find it not in a leaf node does not mean that later on in the remainder of the tree, you might find the value again in a leaf node!
The prototype for this method should be:
bool isProperDescendant( Object value, Object descendant ) throw (InvalidTreeArgument);
3. Without using a BinaryTreeIterator, create a new method called isLeaf that takes an Object and attempts to located its corresponding BinaryTreeNode inside this tree. If it finds such a BinaryTreeNode, this method should return true if that BinaryTreeNode is in fact a leaf in this tree; return false otherwise. If the root of the tree is NULL, your method should throw the InvalidTreeArgument exception.
HINT: Don't quit early. Just because you find it not in a leaf node does not mean that later on in the remainder of the tree, you might find the value again in a leaf node!
The prototype for this method should be:
bool isLeaf( Object value ) throw (InvalidTreeArgument);
Create a test driver that exercises each of these additional features, prints the tree and the results of each new operation.
BinaryTreeNode.h
#ifndef BINARYTREENODE_H
#define BINARYTREENODE_H
#include <iostream>
#include <cstddef>
namespace cs20 {
template <class Object>
class BinaryTreeNode {
public:
BinaryTreeNode( const Object& theElement = Object(),
BinaryTreeNode * theLeftSide = nullptr,
BinaryTreeNode * theRightSide = nullptr);
BinaryTreeNode * duplicate() const;
static int size( BinaryTreeNode * t );
static int height( BinaryTreeNode * t );
// no references to a BinaryTreeNode are returned
// publicly by either BinaryTree or BinaryTreeIterator
// these methods are only called by BinaryTree and
// BinaryTreeIterator
const Object& getElement() const;
BinaryTreeNode* getLeftSide() const;
BinaryTreeNode* getRightSide() const;
void setLeftSide( BinaryTreeNode* node );
void setRightSide( BinaryTreeNode* node );
private:
Object element;
BinaryTreeNode* rightSide;
BinaryTreeNode* leftSide;
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
BinaryTreeNode.cpp
#ifndef BINARYTREENODE_CPP
#define BINARYTREENODE_CPP
#include "BinaryTreeNode.h"
namespace cs20 {
template <class Object>
BinaryTreeNode<Object>::BinaryTreeNode( const Object& theElement,
BinaryTreeNode<Object> * theLeftSide,
BinaryTreeNode<Object> * theRightSide ) {
element = theElement;
rightSide = theRightSide;
leftSide = theLeftSide;
}
template <class Object>
int BinaryTreeNode<Object>::size( BinaryTreeNode<Object> * node ) {
if (node == nullptr )
return( 0 );
else
return( 1 + size( node->rightSide ) + size( node->leftSide ) );
}
template <class Object>
int BinaryTreeNode<Object>::height( BinaryTreeNode<Object> * node ) {
if (node == nullptr )
return( -1 );
else
return( 1 + std::max( height( node->leftSide ), height( node->rightSide ) ) );
}
template <class Object>
BinaryTreeNode<Object> * BinaryTreeNode<Object>::duplicate( ) const {
BinaryTreeNode<Object> * newNode = new BinaryTreeNode<Object>( element );
if (rightSide != nullptr) {
newNode->rightSide = rightSide->duplicate();
}
if (leftSide != nullptr) {
newNode->leftSide = leftSide->duplicate();
}
return( newNode );
}
template <class Object>
const Object& BinaryTreeNode<Object>::getElement() const {
return( element );
}
template <class Object>
BinaryTreeNode<Object>* BinaryTreeNode<Object>::getLeftSide() const {
return( leftSide );
}
template <class Object>
BinaryTreeNode<Object>* BinaryTreeNode<Object>::getRightSide() const {
return( rightSide );
}
template <class Object>
void BinaryTreeNode<Object>::setLeftSide( BinaryTreeNode<Object>* node ) {
leftSide = node;
}
template <class Object>
void BinaryTreeNode<Object>::setRightSide( BinaryTreeNode<Object>* node ) {
rightSide = node;
}
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
LevelOrderIterator.cpp
#ifndef LEVELORDERITERATOR_CPP
#define LEVELORDERITERATOR_CPP
#include "LevelOrderIterator.h"
namespace cs20 {
template <class Object>
LevelOrderIterator<Object>::LevelOrderIterator( const BinaryTree<Object> & theTree ) : BinaryTreeIterator<Object>( theTree ) {
q.enqueue( this->root );
}
template <class Object>
LevelOrderIterator<Object>::~LevelOrderIterator() {
}
template <class Object>
void LevelOrderIterator<Object>::first( ) {
q.makeEmpty();
if (this->root != nullptr) {
q.enqueue( this->root );
advance();
}
}
template <class Object>
void LevelOrderIterator<Object>::advance( ) {
if (q.isEmpty()) {
if (this->current == nullptr)
throw BadIterator();
this->current = nullptr;
}
else {
this->current = q.dequeue();
//if (current->leftSide != nullptr)
// q.enqueue( current->leftSide );
//if (current->rightSide != nullptr)
// q.enqueue( current->rightSide );
if (this->current->getLeftSide() != nullptr)
q.enqueue( this->current->getLeftSide() );
if (this->current->getRightSide() != nullptr)
q.enqueue( this->current->getRightSide() );
}
}
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
BinaryTree.cpp
#ifndef BINARYTREE_CPP
#define BINARYTREE_CPP
#include "BinaryTree.h"
namespace cs20 {
template <class Object>
BinaryTree<Object>::BinaryTree() {
root = nullptr;
}
template <class Object>
BinaryTreeNode<Object> * BinaryTree<Object>::getRoot() const {
return( root );
}
template <class Object>
BinaryTree<Object>::BinaryTree( const BinaryTree<Object>& rhs ) {
root = nullptr;
*this = rhs;
}
template <class Object>
BinaryTree<Object>::BinaryTree( const Object& rootElement ) {
root = new BinaryTreeNode<Object>( rootElement );
}
template <class Object>
BinaryTree<Object>::~BinaryTree() {
makeEmpty();
}
template <class Object>
bool BinaryTree<Object>::isEmpty() const {
return( root == nullptr );
}
template <class Object>
void BinaryTree<Object>::makeEmpty() {
makeEmpty( root );
}
template <class Object>
void BinaryTree<Object>::makeEmpty( NodePtr & node ) {
if (node != nullptr) {
NodePtr r = node->getRightSide();
NodePtr l = node->getLeftSide();
if (r != nullptr)
makeEmpty( r );
if (l != nullptr)
makeEmpty( l );
delete node;
node = nullptr;
}
}
template <class Object>
int BinaryTree<Object>::size() const {
return( BinaryTreeNode<Object>::size( root ) );
}
template <class Object>
int BinaryTree<Object>::height() const {
return( BinaryTreeNode<Object>::height( root ) );
}
template <class Object>
void BinaryTree<Object>::setRightSide( BinaryTree& theRightSide ) {
if (theRightSide.root == nullptr)
throw( InvalidTreeArgument() );
BinaryTreeNode<Object> *child = new BinaryTreeNode<Object>( theRightSide.root->getElement(),
theRightSide.root->getLeftSide(),
theRightSide.root->getRightSide() );
root->setRightSide( child );
if (child != theRightSide.root)
theRightSide.root = nullptr;
}
template <class Object>
void BinaryTree<Object>::setLeftSide( BinaryTree& theLeftSide ) {
if (theLeftSide.root == nullptr)
throw( InvalidTreeArgument() );
BinaryTreeNode<Object> *child = new BinaryTreeNode<Object>( theLeftSide.root->getElement(),
theLeftSide.root->getLeftSide(),
theLeftSide.root->getRightSide() );
root->setLeftSide( child );
if (child != theLeftSide.root)
theLeftSide.root = nullptr;
}
template <class Object>
void BinaryTree<Object>::merge( const Object& rootElement,
BinaryTree & left,
BinaryTree & right ) {
if ( left.root == right.root && left.root != nullptr ) {
std::cerr << "Cannot merge a tree with itself" << std::endl;
throw( InvalidTreeArgument() );
}
else {
NodePtr oldRoot = root;
root = new BinaryTreeNode<Object>( rootElement,
left.root,
right.root );
if (this != &left && this != &right)
makeEmpty( oldRoot );
if (this != &left)
left.root = nullptr;
if (this != &right)
right.root = nullptr;
}
}
// Deep copy of tree
template <class Object>
const BinaryTree<Object>& BinaryTree<Object>::operator =( const BinaryTree<Object>& rhs ) {
if (this != &rhs) {
makeEmpty();
if (rhs.root != nullptr)
root = rhs.root->duplicate();
}
return( *this );
}
template <class Object>
void BinaryTree<Object>::printTree( std::ostream& out ) const {
if (root == nullptr) {
out << "nullptr" << std::endl;
}
else {
printTree( root, out );
out << std::endl;
}
}
template <class Object>
void BinaryTree<Object>::printTree( NodePtr subtree, std::ostream & out ) const {
if (subtree == nullptr) {
out << "nullptr";
}
else {
out << subtree->getElement();
out << " ";
printTree( subtree->getLeftSide(), out );
out << " ";
printTree( subtree->getRightSide(), out );
out << " ";
}
}
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
BinaryTreeIterator.h
#ifndef BINARYTREEITERATOR_H
#define BINARYTREEITERATOR_H
#include <iostream>
#include "BinaryTreeNode.h"
#include "BinaryTree.h"
#include "BadIterator.h"
namespace cs20 {
template <class Object>
class BinaryTreeIterator {
public:
BinaryTreeIterator( const BinaryTree<Object>& theTree );
virtual ~BinaryTreeIterator();
bool isValid() const;
virtual void advance() = 0;
virtual void first() = 0;
const Object& retrieve() const;
//protected:
const BinaryTreeNode<Object> * current;
const BinaryTreeNode<Object> * root;
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
TreeMenu.cpp
// Menu.cpp : Defines the entry point for the console application.
//
#include <iostream>
#include "BadIterator.h"
#include "InvalidTreeArgument.h"
#include "LevelOrderIterator.h"
#include "LevelOrderIterator.cpp"
#include "Queue.h"
#include "Queue.cpp"
#include "QueueNode.h"
#include "QueueNode.cpp"
#include "BinaryTree.h"
#include "BinaryTree.cpp"
#include "BinaryTreeIterator.h"
#include "BinaryTreeIterator.cpp"
#include "BinaryTreeNode.h"
#include "BinaryTreeNode.cpp"
using namespace std;
using namespace cs20;
enum CHOICE {MAKEEMPTY, ISEMPTY, SIZE, HEIGHT, QUIT, PRINT, PRINTNODE, LEVELORDER, SETROOT, SETLEFT, SETRIGHT, GOTOROOT, GOLEFT, GORIGHT };
CHOICE menu();
void printTree( const BinaryTree<int>& t );
int main(int argc, char* argv[]) {
int value;
BinaryTree<int> tree;
BinaryTreeNode<int> * node = nullptr;
BinaryTree<int> lefttree;
BinaryTree<int> righttree;
BinaryTreeNode<int> * leftnode = nullptr;
BinaryTreeNode<int> * rightnode = nullptr;
CHOICE choice;
do {
choice = menu();
switch( choice ) {
case MAKEEMPTY:
tree.makeEmpty();
node = nullptr;
break;
case ISEMPTY:
if (tree.isEmpty()) {
cout << "tree is empty" << endl;
}
else {
cout << "tree is not empty" << endl;
}
break;
case SIZE:
if (node == nullptr) {
cout << "You silly... the current node is nullptr!" << endl;
}
else {
cout << "size of current node=" << BinaryTreeNode<int>::size( node ) << endl;
}
break;
case HEIGHT:
if (node == nullptr) {
cout << "You silly... the current node is nullptr!" << endl;
}
else {
cout << "height of current node=" << BinaryTreeNode<int>::height( node ) << endl;
}
break;
case PRINT:
printTree( tree );
break;
case PRINTNODE:
if (node == nullptr) {
cout << "You silly... the current node is nullptr!" << endl;
}
else {
value = node->getElement();
cout << "value of current node=" << value << endl;
}
break;
case SETLEFT:
try {
cout << "Enter a value for node's leftside: ";
cin >> value;
leftnode = new BinaryTreeNode<int>( value );
node->setLeftSide( leftnode );
} catch( InvalidTreeArgument ita ) {
cout << "InvalidTreeArgument caught!" << endl;
}
break;
case SETRIGHT:
try {
cout << "Enter a value for node's rightside: ";
cin >> value;
rightnode = new BinaryTreeNode<int>( value );
node->setRightSide( rightnode );
} catch( InvalidTreeArgument ita ) {
cout << "InvalidTreeArgument caught!" << endl;
}
break;
case SETROOT:
cout << "Enter root value: ";
cin >> value;
// not sure this is too clever...
tree = BinaryTree<int>( value );
node = tree.getRoot();
break;
case LEVELORDER:
try {
LevelOrderIterator<int> iter( tree );
iter.first();
while( iter.isValid() ) {
value = iter.retrieve();
cout << value << " ";
iter.advance();
}
cout << endl;
}
catch( BadIterator bi ) {
cout << "badIterator exception caught!" << endl;
}
break;
case GOTOROOT:
node = tree.getRoot();
break;
case GOLEFT:
node = node->getLeftSide();
break;
case GORIGHT:
node = node->getRightSide();
break;
case QUIT:
break;
}
} while (choice != QUIT);
return( 0 );
}
void printTree( const BinaryTree<int> & t ) {
t.printTree( cout );
}
CHOICE menu() {
char choice;
CHOICE result;
cout << "(M)akeEmpty (I)sEmpty (S)ize (H)eight setRoo(T) set(L)eftSide set(R)ightSide gotoroot(1) gole(F)t gori(G)ht (P)rint printN(O)de le(V)elOrder (Q)uit: " << endl;
cin >> choice;
switch( choice ) {
case 'M':
case 'm':
result = MAKEEMPTY;
break;
case 'S':
case 's':
result = SIZE;
break;
case 'I':
case 'i':
result = ISEMPTY;
break;
case 'H':
case 'h':
result = HEIGHT;
break;
case 'Q':
case 'q':
result = QUIT;
break;
case 'P':
case 'p':
result = PRINT;
break;
case 'O':
case 'o':
result = PRINTNODE;
break;
case 'T':
case 't':
result = SETROOT;
break;
case 'V':
case 'v':
result = LEVELORDER;
break;
case 'L':
case 'l':
result = SETLEFT;
break;
case 'R':
case 'r':
result = SETRIGHT;
break;
case 'F':
case 'f':
result = GOLEFT;
break;
case 'G':
case 'g':
result = GORIGHT;
break;
case '1':
result = GOTOROOT;
break;
}
return( result );
}
/////////////////////////////////////////////////////////////////////////////////////
QueueNode.cpp
#ifndef QUEUENODE_CPP
#define QUEUENODE_CPP
#include "QueueNode.h"
namespace cs20 {
template <class Object>
QueueNode<Object>::QueueNode( const Object& theElement,
QueueNode<Object> * node ) {
element = theElement;
next = node;
}
template <class Object>
const Object& QueueNode<Object>::getElement() const {
return( element );
}
template <class Object>
QueueNode<Object>* QueueNode<Object>::getNext() const {
return( next );
}
template <class Object>
void QueueNode<Object>::setNext( QueueNode<Object> * node ) {
next = node;
}
template <class Object>
std::ostream& operator <<( std::ostream& outs, const QueueNode<Object> * node ) {
if (node == nullptr) {
outs << "Empty Queue";
}
else {
QueueNode<Object> current = *node;
// yucky loop, but I did not want to build a
// constructor, destructor and equal operator
// for a QueueNode
while( true ) {
Object o = current.element;
outs << o << " ";
if (current.next == nullptr)
break;
else
current = *(current.next);
}
}
outs << std::endl;
return( outs );
}
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
BinaryTree.h
#ifndef BINARYTREE_H
#define BINARYTREE_H
#include <iostream>
#include <cstddef>
#include "BinaryTreeNode.h"
#include "InvalidTreeArgument.h"
namespace cs20 {
template <class Object>
class BinaryTreeIterator;
template <class Object>
class BinaryTree {
public:
BinaryTree();
BinaryTree( const Object& rootElement );
BinaryTree( const BinaryTree& rhs );
~BinaryTree();
bool isEmpty() const;
void makeEmpty();
int size() const;
int height() const;
void merge( const Object& rootElement,
BinaryTree& firstChild,
BinaryTree& nextSibling );
void setRightSide( BinaryTree& theRightSide );
void setLeftSide( BinaryTree& theLeftSide );
const BinaryTree& operator =( const BinaryTree& rhs );
// this is tremendously bad form but I had to do it
// to support the menu-based program
BinaryTreeNode<Object> * getRoot() const;
void printTree( std::ostream& out ) const;
private:
typedef BinaryTreeNode<Object>* NodePtr;
NodePtr root;
void makeEmpty( NodePtr &t );
friend class BinaryTreeIterator<Object>;
void printTree( NodePtr subtree, std::ostream & out ) const;
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
BinaryTreeIterator.cpp
#ifndef BINARYTREEITERATOR_CPP
#define BINARYTREEITERATOR_CPP
#include "BinaryTreeIterator.h"
namespace cs20 {
template <class Object>
BinaryTreeIterator<Object>::BinaryTreeIterator( const BinaryTree<Object> & theTree ) : root( theTree.root ) , current( nullptr ) {
// all assignments performed thru code above
}
template <class Object>
BinaryTreeIterator<Object>::~BinaryTreeIterator() {
}
template <class Object>
bool BinaryTreeIterator<Object>::isValid( ) const {
return( (current != nullptr) );
}
template <class Object>
const Object& BinaryTreeIterator<Object>::retrieve( ) const {
if (!(isValid())) throw BadIterator();
return( current->getElement() );
}
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
LevelOrderIterator.h
#ifndef LEVELORDERITERATOR_H
#define LEVELORDERITERATOR_H
#include <iostream>
#include <cstddef>
#include "BinaryTree.h"
#include "BinaryTreeIterator.h"
#include "Queue.h"
namespace cs20 {
template <class Object>
class LevelOrderIterator : public BinaryTreeIterator<Object> {
public:
LevelOrderIterator( const BinaryTree<Object>& theTree );
virtual ~LevelOrderIterator();
void advance();
void first();
protected:
Queue<const BinaryTreeNode<Object> *> q;
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
InvalidTreeArgument.cpp
#include "InvalidTreeArgument.h"
namespace cs20 {
InvalidTreeArgument::InvalidTreeArgument( const std::string& msg ) : std::logic_error( msg.c_str() ) {}
}
/////////////////////////////////////////////////////////////////////////////////////
BadIterator.cpp
#include "BadIterator.h"
namespace cs20 {
BadIterator::BadIterator( const std::string& msg ) : std::logic_error( msg.c_str() ) {}
}
/////////////////////////////////////////////////////////////////////////////////////
InvalidTreeArgument.h
#ifndef INVALIDTREEARGUMENT_H
#define INVALIDTREEARGUMENT_H
#include <iostream>
#include <string>
namespace cs20 {
class InvalidTreeArgument : public std::logic_error {
public:
InvalidTreeArgument( const std::string& msg = "" );
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
BadIterator.h
#ifndef BADITERATOR_H
#define BADITERATOR_H
#include <iostream>
#include <string>
namespace cs20 {
class BadIterator : public std::logic_error {
public:
BadIterator( const std::string& msg = "" );
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
Queue.cpp
#ifndef QUEUE_CPP
#define QUEUE_CPP
#include "Queue.h"
namespace cs20 {
template <class Object>
Queue<Object>::Queue() {
frontNode = nullptr;
backNode = nullptr;
}
template <class Object>
Queue<Object>::Queue( const Queue<Object>& rhs ) {
frontNode = nullptr;
backNode = nullptr;
*this = rhs;
}
template <class Object>
Queue<Object>::~Queue() {
makeEmpty();
// when empty, frontNode and backNode will already be nullptr
}
template <class Object>
bool Queue<Object>::isEmpty() const {
return( (frontNode == nullptr) );
}
template <class Object>
void Queue<Object>::makeEmpty() {
while (!isEmpty()) {
dequeue();
}
}
template <class Object>
void Queue<Object>::enqueue( const Object& data ) {
QueueNode<Object>* newNode = new QueueNode<Object>( data );
if (isEmpty()) {
frontNode = newNode;
backNode = newNode;
}
else {
backNode->setNext( newNode );
backNode = backNode->getNext();
}
}
template <class Object>
const Object Queue<Object>::dequeue() {
Object frontData = getFront();
QueueNode<Object> * oldFront = frontNode;
frontNode = frontNode->getNext();
delete oldFront;
return( frontData );
}
template <class Object>
const Object& Queue<Object>::getFront() const {
if (isEmpty()) {
throw EmptyQueue();
}
return( frontNode->getElement() );
}
// Deep copy of linked Queue
template <class Object>
const Queue<Object>& Queue<Object>::operator =( const Queue<Object>& rhs ) {
if (this != &rhs) {
makeEmpty();
QueueNode<Object> * rhsFrontNode = rhs.frontNode;
while( rhsFrontNode != nullptr) {
enqueue( rhsFrontNode->getElement() );
rhsFrontNode = rhsFrontNode->getNext();
}
}
return( *this );
}
template <class Object>
std::ostream& operator << ( std::ostream& outs, const Queue<Object>& q ) {
outs << q.frontNode;
return( outs );
}
template <class Object>
std::ostream& operator << ( std::ostream& outs, const Queue<Object>* q ) {
outs << q->frontNode;
return( outs );
}
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
Queue.h
#ifndef QUEUE_H
#define QUEUE_H
#include <iostream>
#include "QueueNode.h"
#include "EmptyQueue.h"
namespace cs20 {
template <class Object>
class Queue {
public:
Queue();
Queue( const Queue& rhs );
~Queue();
bool isEmpty() const;
void makeEmpty();
void enqueue( const Object& data );
const Object dequeue();
const Object& getFront() const;
const Queue& operator =( const Queue& rhs );
// take this out for the student version
friend std::ostream& operator << ( std::ostream& outs, const Queue& q );
friend std::ostream& operator << ( std::ostream& outs, const Queue* q );
private:
QueueNode<Object> * frontNode;
QueueNode<Object> * backNode;
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
QueueNode.h
#ifndef QUEUENODE_H
#define QUEUENODE_H
#include <iostream>
namespace cs20 {
template <class Object>
class QueueNode {
public:
QueueNode( const Object& theElement = Object(), QueueNode * node = nullptr );
friend std::ostream& operator <<( std::ostream& outs, const QueueNode * node );
// these accessors and mutators are called
// from Queue class
// no public methods expose QueueNode instances
// outside the Queue class
const Object& getElement() const;
QueueNode* getNext() const;
void setNext( QueueNode * node );
private:
Object element;
QueueNode* next;
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
EmptyQueue.cpp
#include "EmptyQueue.h"
namespace cs20 {
EmptyQueue::EmptyQueue( const std::string& msg ) : std::logic_error( msg.c_str() ) {}
}
/////////////////////////////////////////////////////////////////////////////////////
EmptyQueue.h
#ifndef EMPTYQUEUE_H
#define EMPTYQUEUE_H
#include <iostream>
#include <string>
namespace cs20 {
class EmptyQueue : public std::logic_error {
public:
EmptyQueue( const std::string& msg = "" );
};
}
#endif
Explanation / Answer
#ifndef BINARYTREENODE_H
#define BINARYTREENODE_H
#include <iostream>
#include <cstddef>
namespace cs20 {
template <class Object>
class BinaryTreeNode {
public:
BinaryTreeNode( const Object& theElement = Object(),
BinaryTreeNode * theLeftSide = nullptr,
BinaryTreeNode * theRightSide = nullptr);
BinaryTreeNode * duplicate() const;
static int size( BinaryTreeNode * t );
static int height( BinaryTreeNode * t );
// no references to a BinaryTreeNode are returned
// publicly by either BinaryTree or BinaryTreeIterator
// these methods are only called by BinaryTree and
// BinaryTreeIterator
const Object& getElement() const;
BinaryTreeNode* getLeftSide() const;
BinaryTreeNode* getRightSide() const;
void setLeftSide( BinaryTreeNode* node );
void setRightSide( BinaryTreeNode* node );
private:
Object element;
BinaryTreeNode* rightSide;
BinaryTreeNode* leftSide;
};
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
BinaryTreeNode.cpp
#ifndef BINARYTREENODE_CPP
#define BINARYTREENODE_CPP
#include "BinaryTreeNode.h"
namespace cs20 {
template <class Object>
BinaryTreeNode<Object>::BinaryTreeNode( const Object& theElement,
BinaryTreeNode<Object> * theLeftSide,
BinaryTreeNode<Object> * theRightSide ) {
element = theElement;
rightSide = theRightSide;
leftSide = theLeftSide;
}
template <class Object>
int BinaryTreeNode<Object>::size( BinaryTreeNode<Object> * node ) {
if (node == nullptr )
return( 0 );
else
return( 1 + size( node->rightSide ) + size( node->leftSide ) );
}
template <class Object>
int BinaryTreeNode<Object>::height( BinaryTreeNode<Object> * node ) {
if (node == nullptr )
return( -1 );
else
return( 1 + std::max( height( node->leftSide ), height( node->rightSide ) ) );
}
template <class Object>
BinaryTreeNode<Object> * BinaryTreeNode<Object>::duplicate( ) const {
BinaryTreeNode<Object> * newNode = new BinaryTreeNode<Object>( element );
if (rightSide != nullptr) {
newNode->rightSide = rightSide->duplicate();
}
if (leftSide != nullptr) {
newNode->leftSide = leftSide->duplicate();
}
return( newNode );
}
template <class Object>
const Object& BinaryTreeNode<Object>::getElement() const {
return( element );
}
template <class Object>
BinaryTreeNode<Object>* BinaryTreeNode<Object>::getLeftSide() const {
return( leftSide );
}
template <class Object>
BinaryTreeNode<Object>* BinaryTreeNode<Object>::getRightSide() const {
return( rightSide );
}
template <class Object>
void BinaryTreeNode<Object>::setLeftSide( BinaryTreeNode<Object>* node ) {
leftSide = node;
}
template <class Object>
void BinaryTreeNode<Object>::setRightSide( BinaryTreeNode<Object>* node ) {
rightSide = node;
}
}
#endif
#include <iostream>
#include "BadIterator.h"
#include "InvalidTreeArgument.h"
#include "LevelOrderIterator.h"
#include "LevelOrderIterator.cpp"
#include "Queue.h"
#include "Queue.cpp"
#include "QueueNode.h"
#include "QueueNode.cpp"
#include "BinaryTree.h"
#include "BinaryTree.cpp"
#include "BinaryTreeIterator.h"
#include "BinaryTreeIterator.cpp"
#include "BinaryTreeNode.h"
#include "BinaryTreeNode.cpp"
using namespace std;
using namespace cs20;
enum CHOICE {MAKEEMPTY, ISEMPTY, SIZE, HEIGHT, QUIT, PRINT, PRINTNODE, LEVELORDER, SETROOT, SETLEFT, SETRIGHT, GOTOROOT, GOLEFT, GORIGHT };
CHOICE menu();
void printTree( const BinaryTree<int>& t );
int main(int argc, char* argv[]) {
int value;
BinaryTree<int> tree;
BinaryTreeNode<int> * node = nullptr;
BinaryTree<int> lefttree;
BinaryTree<int> righttree;
BinaryTreeNode<int> * leftnode = nullptr;
BinaryTreeNode<int> * rightnode = nullptr;
CHOICE choice;
do {
choice = menu();
switch( choice ) {
case MAKEEMPTY:
tree.makeEmpty();
node = nullptr;
break;
case ISEMPTY:
if (tree.isEmpty()) {
cout << "tree is empty" << endl;
}
else {
cout << "tree is not empty" << endl;
}
break;
case SIZE:
if (node == nullptr) {
cout << "You silly... the current node is nullptr!" << endl;
}
else {
cout << "size of current node=" << BinaryTreeNode<int>::size( node ) << endl;
}
break;
case HEIGHT:
if (node == nullptr) {
cout << "You silly... the current node is nullptr!" << endl;
}
else {
cout << "height of current node=" << BinaryTreeNode<int>::height( node ) << endl;
}
break;
case PRINT:
printTree( tree );
break;
case PRINTNODE:
if (node == nullptr) {
cout << "You silly... the current node is nullptr!" << endl;
}
else {
value = node->getElement();
cout << "value of current node=" << value << endl;
}
break;
case SETLEFT:
try {
cout << "Enter a value for node's leftside: ";
cin >> value;
leftnode = new BinaryTreeNode<int>( value );
node->setLeftSide( leftnode );
} catch( InvalidTreeArgument ita ) {
cout << "InvalidTreeArgument caught!" << endl;
}
break;
case SETRIGHT:
try {
cout << "Enter a value for node's rightside: ";
cin >> value;
rightnode = new BinaryTreeNode<int>( value );
node->setRightSide( rightnode );
} catch( InvalidTreeArgument ita ) {
cout << "InvalidTreeArgument caught!" << endl;
}
break;
case SETROOT:
cout << "Enter root value: ";
cin >> value;
// not sure this is too clever...
tree = BinaryTree<int>( value );
node = tree.getRoot();
break;
case LEVELORDER:
try {
LevelOrderIterator<int> iter( tree );
iter.first();
while( iter.isValid() ) {
value = iter.retrieve();
cout << value << " ";
iter.advance();
}
cout << endl;
}
catch( BadIterator bi ) {
cout << "badIterator exception caught!" << endl;
}
break;
case GOTOROOT:
node = tree.getRoot();
break;
case GOLEFT:
node = node->getLeftSide();
break;
case GORIGHT:
node = node->getRightSide();
break;
case QUIT:
break;
}
} while (choice != QUIT);
return( 0 );
}
void printTree( const BinaryTree<int> & t ) {
t.printTree( cout );
}
CHOICE menu() {
char choice;
CHOICE result;
cout << "(M)akeEmpty (I)sEmpty (S)ize (H)eight setRoo(T) set(L)eftSide set(R)ightSide gotoroot(1) gole(F)t gori(G)ht (P)rint printN(O)de le(V)elOrder (Q)uit: " << endl;
cin >> choice;
switch( choice ) {
case 'M':
case 'm':
result = MAKEEMPTY;
break;
case 'S':
case 's':
result = SIZE;
break;
case 'I':
case 'i':
result = ISEMPTY;
break;
case 'H':
case 'h':
result = HEIGHT;
break;
case 'Q':
case 'q':
result = QUIT;
break;
case 'P':
case 'p':
result = PRINT;
break;
case 'O':
case 'o':
result = PRINTNODE;
break;
case 'T':
case 't':
result = SETROOT;
break;
case 'V':
case 'v':
result = LEVELORDER;
break;
case 'L':
case 'l':
result = SETLEFT;
break;
case 'R':
case 'r':
result = SETRIGHT;
break;
case 'F':
case 'f':
result = GOLEFT;
break;
case 'G':
case 'g':
result = GORIGHT;
break;
case '1':
result = GOTOROOT;
break;
}
return( result );
}
/////////////////////////////////////////////////////////////////////////////////////
QueueNode.cpp
#ifndef QUEUENODE_CPP
#define QUEUENODE_CPP
#include "QueueNode.h"
namespace cs20 {
template <class Object>
QueueNode<Object>::QueueNode( const Object& theElement,
QueueNode<Object> * node ) {
element = theElement;
next = node;
}
template <class Object>
const Object& QueueNode<Object>::getElement() const {
return( element );
}
template <class Object>
QueueNode<Object>* QueueNode<Object>::getNext() const {
return( next );
}
template <class Object>
void QueueNode<Object>::setNext( QueueNode<Object> * node ) {
next = node;
}
template <class Object>
std::ostream& operator <<( std::ostream& outs, const QueueNode<Object> * node ) {
if (node == nullptr) {
outs << "Empty Queue";
}
else {
QueueNode<Object> current = *node;
// yucky loop, but I did not want to build a
// constructor, destructor and equal operator
// for a QueueNode
while( true ) {
Object o = current.element;
outs << o << " ";
if (current.next == nullptr)
break;
else
current = *(current.next);
}
}
outs << std::endl;
return( outs );
}
}
#endif
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.