#include <iostream>
#include <iomanip>
#include <string>
class BTree {
// types:
protected:
struct Node {
int value;
Node *pLeft, *pRight;
// constructor.
Node(int value): value(value), pLeft(nullptr), pRight(nullptr) { }
// destructor.
virtual ~Node() { delete pLeft; delete pRight; }
// disabled:
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// prints node.
virtual void print(std::ostream &out)
{
out << "Node " << value;
}
};
// variables:
protected:
Node *_pRoot;
// methods:
public:
// constructor.
BTree(): _pRoot(nullptr) { }
// destructor.
~BTree() { delete _pRoot; }
// disabled:
BTree(const BTree&) = delete;
BTree& operator=(const BTree&) = delete;
// inserts a node.
bool insert(int value) { return insert(_pRoot, value); }
// prints the tree.
void print(std::ostream &out, bool inOrder)
{
if (_pRoot) {
if (inOrder) printInfix(out, _pRoot, 0);
else print(out, _pRoot, 0);
} else out << "EMPTY." << std::endl;
}
// internal methods:
protected:
// creates and inserts a node.
bool insert(Node *&pNode, int value);
// prints a sub-tree.
void print(std::ostream &out, Node *pNode, int indent);
// prints a sub-tree in order.
void printInfix(std::ostream &out, Node *pNode, int indent);
};
bool BTree::insert(Node *&pNode, int value)
{
if (!pNode) {
pNode = new Node(value);
return true;
}
if (value == pNode->value) return false; // ERROR!
return insert(
value < pNode->value ? pNode->pLeft : pNode->pRight, value);
}
void BTree::print(std::ostream &out, Node *pNode, int indent)
{
out << std::setw(indent) << "";
pNode->print(out);
out << std::endl;
indent += 2;
if (pNode->pLeft) print(out, pNode->pLeft, indent);
if (pNode->pRight) print(out, pNode->pRight, indent);
}
void BTree::printInfix(std::ostream &out, Node *pNode, int indent)
{
if (pNode->pLeft) printInfix(out, pNode->pLeft, indent + 2);
out << std::setw(indent) << "";
pNode->print(out);
out << std::endl;
if (pNode->pRight) printInfix(out, pNode->pRight, indent + 2);
}
class BTree2: public BTree {
// types:
protected:
struct Node: public BTree::Node {
int height;
// constructor.
Node(int value, int height):
BTree::Node(value), height(height)
{ }
virtual ~Node() = default;
// disabled:
Node(const Node&) = delete;
Node& operator=(const Node&) = delete;
// prints node.
virtual void print(std::ostream &out)
{
out << "Node " << value << " (height: " << height << ")";
}
};
// methods:
public:
// constructor.
BTree2(): BTree() { }
// destructor.
~BTree2() = default;
// disabled:
BTree2(const BTree2&) = delete;
BTree2& operator=(const BTree2&) = delete;
// inserts a node.
bool insert(int value)
{
return insert((Node*&)_pRoot, value, 0);
}
// internal methods:
protected:
// creates and inserts a node.
bool insert(Node *&pNode, int value, int height);
};
bool BTree2::insert(Node *&pNode, int value, int height)
{
if (!pNode) {
pNode = new Node(value, height);
return true;
}
if (value == pNode->value) return false; // ERROR!
return insert(
(Node*&)(value < pNode->value ? pNode->pLeft : pNode->pRight),
value, pNode->height + 1);
}
// main function
int main()
{
// some test data
int data[] = { 3, 7, 21, 2, 12, 1, 104, 13 };
enum { nData = sizeof data / sizeof data[0] };
// binary tree
{ std::cout << "Binary Tree:" << std::endl;
BTree bTree;
std::cout << "Build..." << std::endl;
for (int value : data) bTree.insert(value);
std::cout << "Print Hierarchy..." << std::endl;
bTree.print(std::cout, false);
std::cout << "Print Sorted..." << std::endl;
bTree.print(std::cout, true);
std::cout << "Destroy..." << std::endl;
std::cout << std::endl;
}
// derived binary tree
{ std::cout << "Derived Binary Tree:" << std::endl;
BTree2 bTree;
std::cout << "Build..." << std::endl;
for (int value : data) bTree.insert(value);
std::cout << "Print Hierarchy..." << std::endl;
bTree.print(std::cout, false);
std::cout << "Print Sorted..." << std::endl;
bTree.print(std::cout, true);
std::cout << "Destroy..." << std::endl;
std::cout << std::endl;
}
// done
return 0;
}