/* definitions are residing in this header since that's how templates get * expanded, we could have a separate bst.cpp is compiler supports export keyword, * instantiations of code are compiled along with the translation units that spawn them */ #ifndef _BST_H_ #define _BST_H_ #include #include #include #include "node.h" using namespace std; template class Bst { public: Bst(); Bst(const Bst &); /* Bst(Node &); */ Bst(const T &); /* above was hairy, just startup a bst from a T t */ ~Bst(); int insert(const T &); int remove(const T &); int list(void) const; private: unsigned int element_count; void traverse(Node *) const; void free(); void freePostOrder(Node *); protected: Node *root; }; template Bst::Bst() : element_count(0), root(NULL) { } template Bst::Bst(const Bst& tree) { this->free(); /* still a shallow copy, dupe it! */ this->root = tree.root; } template Bst::Bst(const T& t) { Node *first = new Node(t); this->root = first; } template Bst::~Bst() { this->free(); } template int Bst::insert(const T& e) { Node *iter = this->root; Node *new_node = new Node(e); while (iter) { if (iter->getVal() == e) { std::cout << e << " is already in the tree" << std::endl; return 1; } else if (iter->getVal() < e) { if (&iter->getRight() == NULL) { iter->setRight((new_node)); return 1; } else iter = &iter->getRight(); /* taking addr of alias/reference? */ } else { if (&iter->getLeft() == NULL) { iter->setLeft((new_node)); return 1; } else iter = &iter->getLeft(); } } std::cout << "creating root node " << e << endl; this->root = new_node; return 0; } template int Bst::remove(const T& e) { /* assign the value of leftmost subtree of nodes right child to node to be * removed, and delete the leaf where value was taken from */ if (!this->root) return 1; Node *iter = this->root; while (iter) { if (iter->getVal() < e) { /* working on right subtree */ if (&iter->getRight() && (iter->getRight().getVal() == e)) /* lookahead */ { Node *child_left = &iter->getRight().getLeft(); Node *child_right = &iter->getRight().getRight(); Node *node_toremove = &iter->getRight(); if (!child_left && !child_right) { /* leaf */ delete node_toremove; iter->setRight(NULL); } else if (child_left && child_right) { /* node to be remove has 2 children */ if (&child_right->getLeft() == NULL) { /* move up righ subtree if right child has no left child */ child_right->setLeft(&node_toremove->getLeft()); iter->setRight(child_right); delete node_toremove; } else { Node *iter = child_right; while (&iter->getLeft().getLeft()) iter = &iter->getLeft(); /* seek */ node_toremove->setVal(iter->getLeft().getVal()); delete &iter->getLeft(); iter->setLeft(NULL); } } else { /* got one child, delete e and link child to grandfather */ if (child_left) iter->setRight(child_left); else iter->setRight(child_right); delete node_toremove; } return 0; } else iter = &iter->getRight(); } else if (iter->getVal() > e) { /* working with left subtree */ if (&iter->getLeft() && (iter->getLeft().getVal() == e)) /* lookahead */ { Node *child_left = &iter->getLeft().getLeft(); Node *child_right = &iter->getLeft().getRight(); Node *node_toremove = &iter->getLeft(); if (!child_left && !child_right) { /* leaf */ delete node_toremove; iter->setLeft(NULL); return 0; } else if (child_left && child_right) { /* node to be remove has 2 children */ if (&child_right->getLeft() == NULL) { /* move up righ subtree if right child has no left child */ child_right->setLeft(&node_toremove->getLeft()); iter->setLeft(child_right); delete node_toremove; } else { Node *iter = child_right; while (&iter->getLeft().getLeft()) iter = &iter->getLeft(); /* seek */ node_toremove->setVal(iter->getLeft().getVal()); delete &iter->getLeft(); iter->setLeft(NULL); } } else { /* got one child, delete e and link child to grandfather */ if (child_left) iter->setLeft(child_left); else iter->setLeft(child_right); delete node_toremove; } return 0; } else iter = &iter->getLeft(); } else { /* root removal */ /* assign root left subtree into lowest leaf in the right subtree */ if ((&this->root->getLeft() == NULL) && (&this->root->getRight() == NULL)) { delete this->root; this->root = NULL; return 0; } Node *iter = &this->root->getRight(); while (&iter->getLeft()) iter = &iter->getLeft(); iter->setLeft(&this->root->getLeft()); /* set left subtree */ this->root = &root->getRight(); delete this->root; return 0; } } /* not in the tree */ return 2; } template int Bst::list(void) const { if (!this->root) return 1; this->traverse(this->root); return 0; } template void Bst::traverse(Node *node) const { if (!node) return; this->traverse(&node->getLeft()); std::cout << node->getVal() << " " << endl; this->traverse(&node->getRight()); } template void Bst::free(void) { if (this->root) this->freePostOrder(this->root); } template void Bst::freePostOrder(Node *node) { if (!node) return; this->freePostOrder(&node->getLeft()); this->freePostOrder(&node->getRight()); #ifdef DEBUGMSG std::cout << "nuking " << node->getVal() << std::endl; #endif delete node; } #endif