In: Computer Science
For this computer assignment, you are to write a C++ program to implement a class for binary trees. To deal with variety of data types, implement this class as a template.
Most of the public member functions of the BinaryTree class call private member functions of the class (with the same name). These private member functions can be implemented as either recursive or non-recursive, but clearly, recursive versions of these functions are preferable because of their short and simple implementations in code. However, they require more memory and usually slower than their non-recursive versions in execution, especially for a large amount of input data.
#ifndef H_BINARYTREE
#define H_BINARYTREE
template class BinaryTree{
public:
BinaryTree(); // default constructor
unsigned getSize() const; // returns size of tree
unsigned getHeight() const; // returns height of tree
virtual void Insert(const T&); // inserts node in tree
void Inorder(void (*)(const T&)); // inorder traversal of tree
protected:
Node *root; // root of tree
private:
unsigned _getSize(Node *) const; // private version of getSize()
unsigned _getHeight(Node *) const; // private version of getHeight()
void _Insert(Node *&, const T&); // private version of Insert()
void _Inorder(Node *, void (*)(const T&)); // private version of Inorder()
};
#endif // End of H_BINARYTREE
Because of information hiding, a client is not permitted to access the binary tree directly, so the root of the tree is kept protected (not private because of future implementations of derived classes from the base class of the BinaryTree), so it cannot be passed as an argument to any of the public functions of the tree. It is essential to have private utility functions, which act as interface between a client and the tree. The Insert() function of the BinaryTree class is described as follows:
typedef enum {left_side, right_side } SIDE; SIDE rnd(){ return rand()%2 ? right_side : left_side; }// End of rnd()
Put the implementation of your BinaryTree class in the header file binarytree.h. Definition of the class Node, which represents the nodes in a binary tree, can be found in the header file node.h. To use the class Node in your program, include the header file node.h, inserting #include "node.h" at the top of your header file.
The source file binarytreeDriver.cc contains the driver program. In addition to the main() routine, it has the implementations of the following routines (as templates) and the definitions of the two RNGs used in the main() routine.
The unary function print() can be used as an argument to the member functions Inorder() to print the value of its argument x. The function printValues() does the followings:
The class RND1 can be used to generate random integers in the range [LOW1 = –999, HIGH1 = 999] and the class RND2 can be used to generate random floating-point numbers in the range [LOW2 = –999.99, HIGH2 = 999.99]. The function objects RND1() and RND2(), generated from these classes, are used to fill in the random values in vector containers vector A(N1) and vector B(N2) by using the generate() function in the STL, where N1 = 100 and N2 = 50 are the sizes of these two vectors.
The main() routine copies the random values from vectors A and B and inserts them in the binary trees first and second, respectively. At the end, the data values in the binary trees first and second are printed out on stdout with LSIZE = 12 numbers in a single line.
Put the implementation of your BinaryTree class in the header file binarytree.h. Definition of the class Node, which represents the nodes in a binary tree, can be found in the header file node.h. To use the class Node in your program, include the header file node.h, inserting #include "node.h" at the top of your header file.
The source file binarytreeDriver.cc contains the driver program. In addition to the main() routine, it has the implementations of the following routines (as templates) and the definitions of the two RNGs used in the main() routine.
The unary function print() can be used as an argument to the member functions Inorder() to print the value of its argument x. The function printValues() does the followings:
The class RND1 can be used to generate random integers in the range [LOW1 = –999, HIGH1 = 999] and the class RND2 can be used to generate random floating-point numbers in the range [LOW2 = –999.99, HIGH2 = 999.99]. The function objects RND1() and RND2(), generated from these classes, are used to fill in the random values in vector containers vector A(N1) and vector B(N2) by using the generate() function in the STL, where N1 = 100 and N2 = 50 are the sizes of these two vectors.
The main() routine copies the random values from vectors A and B and inserts them in the binary trees first and second, respectively. At the end, the data values in the binary trees first and second are printed out on stdout with LSIZE = 12 numbers in a single line.
BINARYTREE.CC
#include <math.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <vector>
using namespace std;
#include "binarytree.h"
#define SEED 1 // seed for RNGs
#define N1 100 // size of 1st vector container
#define LOW1 -999 // low val for rand integer
#define HIGH1 999 // high val for rand integer
#define N2 50 // size of 2nd vector container
#define LOW2 -99999 // low val for rand float
#define HIGH2 99999 // high val for rand float
#define PREC 2 // no of digits after dec pt
#define LSIZE 12 // no of vals printed on line
#define ITEM_W 7 // no of spaces for each item
// prints single val
template <typename T>
void print(const T&);
// prints data vals in tree
template <typename T>
void print_vals(BinaryTree<T>&, const string&);
// class to generate rand ints
class RND1 {
private:
int low, high;
public:
RND1(const int& l = 0, const int& h = 1) : low(l), high(h) {}
int operator()() const { return rand() % (high - low + 1) + low; }
};
// class to generate rand floats
class RND2 {
private:
int low, high, prec;
public:
RND2(const int& l = 0, const int& h = 1, const int& p = 0) : low(l), high(h), prec(p) {}
float operator()() const { return (static_cast<float>(rand() % (high - low + 1) + low)) / pow(10, prec); }
};
// prints val passed as argument
template <typename T>
void print(const T& x) {
static unsigned cnt = 0;
cout << setw(ITEM_W) << x << ' ';
cnt++;
if (cnt % LSIZE == 0) cout << endl;
}
// prints size and height of bin tree and data val in
// each node in inorder
template <typename T>
void print_vals(BinaryTree<T>& tree, const string& name) {
cout << name << ": "; // print name of tree
// print size and height of tree
cout << "size = " << tree.getSize() << ", ";
cout << "height = " << tree.getHeight() << endl << endl;
// print data values of tree in inorder
cout << "Data values in '" << name << "' inorder:\n\n";
tree.Inorder(print);
cout << endl;
}
// driver program: to test several member functions of BinaryTree class
int main() {
srand(SEED); // set seed for RNGs
// create 1st vector and fill it with rand ints
vector<int> A(N1);
generate(A.begin(), A.end(), RND1(LOW1, HIGH1));
// create binary tree with int vals in vector A,
// and print all vals of tree
BinaryTree<int> first;
for (unsigned i = 0; i < A.size(); i++) first.Insert(A[i]);
print_vals(first, "first");
cout << endl;
// create 2nd vector and fill it with rand floats
vector<float> B(N2);
generate(B.begin(), B.end(), RND2(LOW2, HIGH2, PREC));
// create binary tree with float vals in vector B,
// and print all vals of tree
BinaryTree<float> second;
for (unsigned i = 0; i < B.size(); i++) second.Insert(B[i]);
print_vals(second, "second");
cout << endl;
return 0;
}
The entire code has been given below , I hope you understood the code and feel free to ask if you have any doubts and don't forget to give upvote as it means a lot and took so much time to code it up.Thanks:)
Node.h
#ifndef NODE_H
#define NODE_H
template <class T> class binTree;
template <class T> class Node
{
friend class binTree <T>;
public:
//The node defualt constructor
Node ( const T& =T ( ), Node <T>* = 0, Node <T>* =
0 );
private:
T nodeContent;
Node <T> *leftChild, *childRight;
};
// default constructor
template <class T>
Node <T>:: Node( const T& temp, Node <T>* newLeft,
Node <T>* newRight )
{
nodeContent = temp;
leftChild = newLeft;
childRight = newRight;
}
#endif
binTree.h
#ifndef BINTREE_H
#define BINTREE_H
#include "Node.h"
template <class T> class binTree
{
public:
binTree ( );
int height ( ) const;
virtual void insert ( const T& );
void inOrder ( void ( * ) ( T& ));
protected:
Node <T>* root;
private:
int height ( Node <T>* ) const;
void insert ( Node <T>*&, const T& );
void inOrder ( Node <T>*, void ( * ) ( T& ));
};
//function definitions
template <class T>
binTree <T>::binTree( )
{
//set the root
root = 0;
}
// returns height of tree
template <class T>
int binTree <T>::height( ) const
{
return height( root ); // call recursive
}
//to insert the node in the binary tree
//recursive function
template <class T>
void binTree <T>::insert( const T& temp )
{
insert( root, temp );
}
//To perform inorder traversal of the tree
template <class T>
void binTree <T>::inOrder( void ( *print ) ( T& ) )
{
inOrder( root, print );
}
// private version of height
template <class T>
int binTree <T>::height( Node <T>* ptr ) const
{
if( ptr == 0 )
{
return 0;
}
else
{
int heightleft = height( ptr->leftChild );
int heigRight = height( ptr->childRight );
if( heightleft > heigRight )
{
return 1 + heightleft;
}
else
{
return 1 + heigRight;
}
}
}
template <class T>
void binTree <T>::insert( Node <T>* & nod, const
T& temp )
{
if( nod == 0 )
{
Node <T> * newNode;
newNode = new Node <T>( temp );
nod = newNode;
}
else
{
int heightleft = height( nod->leftChild );
int heigRight = height( nod->childRight );
if( heightleft <= heigRight )
{
insert( nod->leftChild, temp );
}
else
{
insert( nod->childRight, temp );
}
}
}
//inorder traversal
template <class T>
void binTree <T>::inOrder( Node <T>* nod, void ( *print
) ( T& ) )
{
if( nod != NULL )
{
inOrder( nod->leftChild, print );
print( nod->nodeContent );
inOrder( nod->childRight, print );
}
}
#endif
prog6.cpp
#include <iostream>
#include<cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
#include "binTree.h"
using namespace std;
class RND1{
int x;
public:
static int RND(){
srand(time(NULL));
return (-999+ (rand() % (static_cast<int>(999 +999 +
1))));
srand(time(NULL));
}
};
class RND2{
float randm;
public:
static float RND()
{
srand(time(NULL));
return -999.99 + static_cast <float> (rand()) /( static_cast
<float> (RAND_MAX/(999.99+999.99)));
}
};
template <class T>
void print(T a)
{
cout<<a<<" ";
}
int main()
{
srand(unsigned(time(0)));
vector<int> A(100);
vector<float> B(50);
RND1 obj3=RND1();
std::cout << "\nIn order traversal of int tree:
\n";
binTree <int> tr=binTree <int> ( );
int count=1;
generate(A.begin(), A.end(), &RND1::RND);
for (auto iv: A) {
tr.insert(iv);
}
tr.inOrder(&print);
//float tree
std::cout << "\n\nIn order traversal of float tree:
\n";
binTree <float> tr1=binTree <float> ( );
generate(B.begin(), B.end(), &RND2::RND);
for (auto iv: B) {
tr1.insert(iv);
}
tr1.inOrder(&print);
//print heights
cout<<"\nint tree height"<<tr.height();
cout<<"\nfloat tree
height"<<tr1.height();
cout<<endl;
system("pause");
return 0;
}