tree_t class stores a link to the root node.
NULL.
tree.cpp) for the following
tree_t interface (tree.h):
#ifndef TREE_H
#define TREE_H
// forward declcarations
template <typename T> class tree_t;
template <typename T> std::ostream& operator<<(std::ostream&, const tree_t<T>&);
template <typename T>
class tree_t {
private:
struct node_t // an all public class with data only, no member ftns
{
T data;
node_t *left;
node_t *right;
node_t(const T& d = T(), node_t *l = NULL, node_t *r = NULL) : \
data(d), left(l), right(r) \
{ };
};
public:
// constructors (overloaded)
tree_t();
// copy constructor
//tree_t(const tree_t& rhs);
// destructors
~tree_t() { clear(); }
// friends -- note the extra <> telling the compiler to instantiate
// a templated version of the operator<< -- <T> is also legal,
// i.e.,
// friend std::ostream& operator<< <T>(std::ostream& s, const tree_t&);
friend
std::ostream& operator<< <>(std::ostream& s, const tree_t& rhs);
friend
std::ostream& operator<<(std::ostream& s, tree_t *rhs)
{ return(s << (*rhs)); }
void inorder(std::ostream& s, node_t* const &t) const;
// assignment operator
const tree_t& operator=(const tree_t&);
// operators
// members
bool empty() const { return root == NULL ? true : false;}
bool contains(const T& x) const { return contains(x,root); }
void insert(const T& x) { insert(x, root); }
void clear() { clear(root); }
private:
node_t *root;
bool contains(const T&, node_t* ) const;
void insert(const T& x, node_t* &t);
void clear(node_t* &);
node_t* clone(node_t* ) const;
};
#endif
Details
clear,
insert, and
inorder are recursive methods.
That is, in order to make a node empty, you must first make
its subtrees empty. Thus, clear is called
recursively on the subtrees first before deleting the current
node (if it is not NULL already). Similarly,
insert is called recursively on subtrees to find
the correct insertion point.
clear, insert, and
operator<< call the private versions
with the root as the starting point.
insert uses a reference to
a pointer. The reason that we need to be able to change where
the node points when we insert (e.g., if the node points to
NULL, we need to change it to point to the new
node_t we are inserting). We could use a pointer
to a pointer; however, C++'s references allow simpler notation.
clear method:
clear on
its children.
NULL. Setting the
node to NULL is effective outside
of the method call because the node passed in as a
reference to a pointer.
insert method (3 cases):
NULL,
insert this value as that node.
inorder method (inorder printing):
inorder on the left child.
inorder on the right child.
#include <iostream>
#include <cstdlib>
#include <sys/time.h>
#include "pairs.h"
#include "tree.h"
int main();
int main()
{
int num;
tree_t<int> tree;
tree_t<pairs_t> ptree;
struct timeval tp;
// get time of day
gettimeofday(&tp,NULL);
// use microseconds as the seed
//srand((unsigned int)tp.tv_usec);
srand((unsigned int)1337);
// sort while inserting, thus maintaining list as priority queue
std::cout << "Inserting:" << std::endl;
for(int i=0;i<10;i++) {
num = static_cast<int>((float)rand()/(float)RAND_MAX*100.0);
std::cout << num << " ";
tree.insert(num);
}
std::cout << std::endl;
tree.insert(57);
std::cout << "Tree contains 57? " << tree.contains(57) << std::endl;
std::cout << "Tree: " << tree << std::endl;
ptree.insert(pairs_t(45.0,'b'));
ptree.insert(pairs_t(37.2,'c'));
ptree.insert(pairs_t(42.6,'a'));
ptree.insert(pairs_t(53.7,'d'));
std::cout << "Pair Tree: " << ptree << std::endl;
}
Inserting:
1 86 24 21 30 74 89 64 21 68
Tree contains 57? 1
Tree: 1 21 24 30 57 64 68 74 86 89
Pair Tree: ('a',42.6) ('b',45) ('c',37.2) ('d',53.7)
tar.gz
archive of your lab##/ directory, including:
README file containing
Makefile
.h headers and .cpp source)
make clean before tar)
sendlab notes