13.6.2.1. Tree Example 1: One Template Variable
The Tree template example program consists of three files:
Tree.h: demonstrates how to create a general data structure based on templates (notice that the template class and all functions must be in a header file)
Employe.h: a simple class instances of which are stored in the Tree
Employee.cpp: simple driver that defines and uses a Tree to store instances of Employee - demonstrates how to create an instance of a template class
#include <iostream>
using namespace std;
template <class T>
class Tree
{
private:
T data;
Tree* left = nullptr; // 1
Tree* right = nullptr;
public:
//Tree() : left(nullptr), right(nullptr) {} // 2
~Tree();
T * insert(T & data);
T * search(T & data);
void list() { right->_list(); } // 3
private:
void _list(); // 4
};
Tree.h: class specification .
Support for initializing member variables in the class specification was added with the ANSI 2014 language standard
Prior to the 2014 standard, member variables were only initialized by the constructor
The public interface for the list operation calls the private _list function, initiating the descent on the right sub-tree. The simple list function contributes to a "clean" public interface, allowing the class designer to implement _list as a recursive function.
The private _list function does most of the work of the list operation.
template <class T>
Tree<T> ::~Tree()
{
if (left != nullptr)
delete left;
if (right != nullptr)
delete right;
}
Tree.h: destructor . Although perhaps not immediately obvious, the destructor is a recursive function: delete left
and delete right
each trigger a recursive call to the destructor function.
template <class T>
T * Tree<T> ::insert(T & data)
{
Tree* root = this; // 1
Tree* down = right;
while (down != nullptr && !(down->data == data)) // 2
{
root = down;
if (data < down->data)
down = down->left;
else
down = down->right;
}
if (down != nullptr) // 3
return &down->data;
down = new Tree; // 4
down->data = data;
if (data < root->data) // 5
root->left = down;
else
root->right = down;
return &down->data; // 6
}
Tree.h: insert function . There are many ways to implement the insert operation; this implementation has three important characteristics:
it does not allow duplicate data in the tree
it returns a pointer to the stored data, either newly or previously inserted
it uses iteration, a while loop, to descend the tree rather than recursion
This implementation requires that operator<
and operator==
are implemented for the class that replaces the template variable T.
root and down are used to locate the insertion point
Loops until (a) the bottom of a sub-tree is located or (b) a previously inserted copy of the data is found. It is more common to implement operator==
than it is is to implement operator!=
, so the equality operator is used here with the negation operator ( !
)
Returns a pointer to the previously inserted data if present in the tree
Creates a new tree node and installs the data if the data is not present in the tree
Binary trees are ordered. A typical ordering is to insert new data in the left sub-tree if it is less than the data in the root of the current sub-tree; other wise it is inserted in the right sub-tree
Returns a pointer to the newly inserted data
template <class T>
T * Tree<T> ::search(T & data)
{
Tree* root = right; // 1
while (root != nullptr && !(root->data == data)) // 2
{
if (data < root->data)
root = root->left;
else
root = root->right;
}
if (root == nullptr) // 3
return nullptr;
else
return &root->data;
}
Tree.h: search function . The search operation returns a pointer to the data if it is found, otherwise it returns nullptr
.
root is used to descend the tree while looking for the tree node that stores the searched for data
Loops until (a) the bottom of the tree is located or (b) the searched for data is located.
Returns a pointer to located data or nullptr if the data is not found.
template <class T>
void Tree<T> ::_list()
{
if (left != nullptr)
left->_list();
cout << data << endl;
if (right != nullptr)
right->_list();
}
Tree.h: private _list function .
The _list function recursively descends the tree printing the stored data in-order (pre-order and post-order are achieved by moving the cout statement to the top or bottom of the function respectively). The _list function assumes that operator<<
is overloaded for the template class that replaces T .
#include <iostream>
#include <string>
using namespace std;
class Employee
{
private:
string name;
int id;
public:
Employee(string n = "", int en = 0) : name(n), id(en) {}
bool operator==(Employee& e) { return name == e.name; } // 1
bool operator<(Employee& e) { return name < e.name; } // 2
friend ostream& operator<<(ostream& out, Employee& me) // 3
{
out << me.name << " " << me.id;
return out;
}
};
Employee.h: Employee class specification .
Required for Tree.insert and Tree.search
Required for Tree.insert and Tree.search
Required for Tree.list
#include <iostream>
#include <string>
#include "Tree.h"
#include "Employee.h"
using namespace std;
int main()
{
Tree<Employee> tree;
string name;
while (true)
{
cout << "N\tEnter a new Employee" << endl;
cout << "S\tSearch for an Employee" << endl;
cout << "L\tList all Employees" << endl;
cout << "E\tExit" << endl;
cout << "Operation: ";
char operation;
cin >> operation;
cin.ignore();
switch (operation)
{
case 'N' // create a new Employee and insert it into the Tree
case 'n':
{
cout << "Employee name: ";
getline(cin, name);
int number;
cout << "Employee Number: ";
cin >> number;
cin.ignore();
Employee employee(name, number); // Data
tree.insert(employee);
break;
}
case 'S': // search for an exiting Employee in the Tree
case 's':
{
cout << "Employee name: ";
getline(cin, name);
Employee employee(name);
Employee* e = tree.search(employee);
if (e != nullptr)
cout << "Employee: " << *e << endl;
else
cout << name << " NOT FOUND" << endl;
break;
}
case 'L': // list all of the Employees in the Tree
case 'l':
tree.list();
break;
case 'E': // exit the program
case 'e':
return 0;
//exit(0); // ends the program but doesn't call the destructor
default:
cerr << "Unrecognized operation: \"" << operation << "\"" << endl;
break;
}
}
return 0;
}
Employee.cpp . A client program that uses the Tree template class. The highlighted statement demonstrates how to define an instance of the Tree class and to specify the class type (Employee) stored in the Tree. The class name "Employee" replaces the template variable T when the program is compiled.
Downloadable Code
Back |
Chapter TOC |
Next