// Partial implementation of binary-tree based set class similar to std::set. // The iterator increment & decrement operations have been omitted. #ifndef ds_set_h_ #define ds_set_h_ #include #include // ------------------------------------------------------------------- // TREE NODE CLASS template class TreeNode { public: TreeNode() : left(NULL), right(NULL) {} TreeNode(const T& init) : value(init), left(NULL), right(NULL) {} T value; TreeNode* left; TreeNode* right; }; // ------------------------------------------------------------------- // TREE NODE ITERATOR CLASS template class tree_iterator { public: tree_iterator() : ptr_(NULL) {} tree_iterator(TreeNode* p) : ptr_(p) {} tree_iterator(const tree_iterator& old) : ptr_(old.ptr_) {} ~tree_iterator() {} tree_iterator& operator=(const tree_iterator& old) { ptr_ = old.ptr_; return *this; } // operator* gives constant access to the value at the pointer const T& operator*() const { return ptr_->value; } // comparions operators are straightforward bool operator== (const tree_iterator& rgt) { return ptr_ == rgt.ptr_; } bool operator!= (const tree_iterator& rgt) { return ptr_ != rgt.ptr_; } private: // representation TreeNode* ptr_; }; // ------------------------------------------------------------------- // DS_SET CLASS template class ds_set { public: ds_set() : root_(NULL), size_(0) {} ds_set(const ds_set& old) : size_(old.size_) { root_ = this->copy_tree(old.root_); } ~ds_set() { this->destroy_tree(root_); root_ = NULL; } ds_set& operator=(const ds_set& old) { if (&old != this) { this->destroy_tree(root_); root_ = this->copy_tree(old.root_); size_ = old.size_; } return *this; } typedef tree_iterator iterator; int size() const { return size_; } bool operator==(const ds_set& old) const { return (old.root_ == this->root_); } // FIND, INSERT & ERASE iterator find(const T& key_value) { return find(key_value, root_); } std::pair< iterator, bool > insert(T const& key_value) { return insert(key_value, root_); } int erase(T const& key_value) { return erase(key_value, root_); } // OUTPUT & PRINTING friend std::ostream& operator<< (std::ostream& ostr, const ds_set& s) { s.print_in_order(ostr, s.root_); return ostr; } void print_as_sideways_tree(std::ostream& ostr) const { print_as_sideways_tree(ostr, root_, 0); } // ITERATORS iterator begin() const { if (!root_) return iterator(NULL); TreeNode* p = root_; while (p->left) p = p->left; return iterator(p); } iterator end() const { return iterator(NULL); } private: // REPRESENTATION TreeNode* root_; int size_; // PRIVATE HELPER FUNCTIONS TreeNode* copy_tree(TreeNode* old_root) { if (old_root == NULL) return NULL; TreeNode *answer = new TreeNode(); answer->value = old_root->value; answer->left = copy_tree(old_root->left); answer->right = copy_tree(old_root->right); return answer; } void destroy_tree(TreeNode* p) { if (!p) return; destroy_tree(p->right); destroy_tree(p->left); delete p; } iterator find(const T& key_value, TreeNode* p) { if (!p) return iterator(NULL); if (p->value > key_value) return find(key_value, p->left); else if (p->value < key_value) return find(key_value, p->right); else return iterator(p); } std::pair insert(const T& key_value, TreeNode*& p) { if (!p) { p = new TreeNode(key_value); this->size_++; return std::pair(iterator(p), true); } else if (key_value < p->value) return insert(key_value, p->left); else if (key_value > p->value) return insert(key_value, p->right); else return std::pair(iterator(p), false); } int erase(T const& key_value, TreeNode* &p) { if (!p) return 0; // look left & right if (p->value < key_value) return erase(key_value, p->right); else if (p->value > key_value) return erase(key_value, p->left); // Found the node. Let's delete it assert (p->value == key_value); if (!p->left && !p->right) { // leaf delete p; p=NULL; } else if (!p->left) { // no left child TreeNode* q = p; p=p->right; delete q; } else if (!p->right) { // no right child TreeNode* q = p; p=p->left; delete q; } else { // Find rightmost node in left subtree TreeNode* &q = p->left; while (q->right) q = q->right; p->value = q->value; int check = erase(q->value, q); assert (check == 1); } return 1; } void print_in_order(std::ostream& ostr, const TreeNode* p) const { if (p) { print_in_order(ostr, p->left); ostr << p->value << "\n"; print_in_order(ostr, p->right); } } void print_as_sideways_tree(std::ostream& ostr, const TreeNode* p, int depth) const { if (p) { print_as_sideways_tree(ostr, p->right, depth+1); for (int i=0; ivalue << "\n"; print_as_sideways_tree(ostr, p->left, depth+1); } } }; #endif