/* * bintree.cpp * * Created on: 27.11.2015 г. * Author: trifon */ #ifndef _BINTREE_CPP #define _BINTREE_CPP #include #include using namespace std; template struct TreeNode { T data; TreeNode *left, *right; TreeNode(T const& _data = T(), TreeNode* _left = NULL, TreeNode* _right = NULL) : data(_data), left(_left), right(_right) {} }; template class BinaryTree; template class BinaryTreePosition { private: TreeNode** p; public: BinaryTreePosition(TreeNode*& rp) : p(&rp) {} operator bool() const { return *p != NULL; } bool operator!() const { return *p == NULL; } T& operator*() const { return (*p)->data; } BinaryTreePosition operator+() const { if (*p == NULL) return *this; return BinaryTreePosition((*p)->right); } BinaryTreePosition operator-() const { if (*p == NULL) return *this; return BinaryTreePosition((*p)->left); } friend class BinaryTree; }; template class BinaryTree { private: TreeNode* r; TreeNode* copyNode(TreeNode* n) { if (n == NULL) return n; cout << "Copying tree" << endl; return new TreeNode(n->data, copyNode(n->left), copyNode(n->right)); } void eraseNode(TreeNode* n) { if (n != NULL) { eraseNode(n->left); eraseNode(n->right); delete n; } } BinaryTree(TreeNode* p) : r(copyNode(p)) {} void assignFrom(TreeNode*& to, TreeNode*& from) { eraseNode(to); to = from; from = NULL; } public: using P = BinaryTreePosition; protected: void assignFrom(P to, P from) { assignFrom(*to.p, *from.p); } public: BinaryTree() : r(NULL) {} BinaryTree(T const& x, BinaryTree&& lt = BinaryTree(), BinaryTree&& rt = BinaryTree()) { r = new TreeNode(x); assignFrom(r->left, lt.r); assignFrom(r->right, rt.r); } BinaryTree(BinaryTree const& bt) : r(copyNode(bt.r)) { } BinaryTree& operator=(BinaryTree const& bt) { if (this != &bt) { eraseNode(r); r = copyNode(bt.r); } return *this; } ~BinaryTree() { eraseNode(r); } void assignFrom(P pos, BinaryTree&& t) { assignFrom(pos, t.root()); } void deleteAt(P pos) { TreeNode* tmp = NULL; assignFrom(*pos.p, tmp); } /* T root() const { if (r == NULL) return T(); return r->data; } */ P root() { return P(r); } BinaryTree leftTree() const { return BinaryTree(r->left); } BinaryTree rightTree() const { return BinaryTree(r->right); } bool empty() const { return r == NULL; } }; template ostream& operator<<(ostream& os, BinaryTree const& bt) { if (bt.empty()) return os << '.'; return os << '(' << *bt.root() << ' ' << bt.leftTree() << ' ' << bt.rightTree() << ')'; } template ostream& operator<<(ostream& os, BinaryTreePosition pos) { if (!pos) return os << '.'; return os << '(' << *pos << ' ' << -pos << ' ' << +pos << ')'; } template void printDOT(ofstream&, BinaryTreePosition); template void printEdge(ofstream& dot, BinaryTreePosition from, BinaryTreePosition to) { if (to) { dot << '"' << *from << "\" -> \"" << *to << "\";\n"; printDOT(dot, to); } } template void printDOT(ofstream& dot, BinaryTreePosition pos) { if (pos) { printEdge(dot, pos, -pos); printEdge(dot, pos, +pos); } } template void printDOT(BinaryTree& t, char const* filename) { ofstream dot(filename); dot << "digraph tree { "; printDOT(dot, t.root()); dot << "}"; } #endif