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