#ifndef BINARY_SEARCH_TREE_ITERATIVE #define BINARY_SEARCH_TREE_ITERATIVE #ifndef nullptr #define nullptr 0 #endif #include #include #include "Exception.h" #include "Binary_search_node_iterative.h" template class Binary_search_tree { private: Binary_search_node *root_node; Binary_search_node *root() const; public: Binary_search_tree(); ~Binary_search_tree(); bool empty() const; int size() const; int height() const; Type front() const; Type back() const; bool find( Type const & ) const; bool insert( Type const & ); bool erase( Type const & ); void clear(); }; template Binary_search_tree::Binary_search_tree(): root_node( nullptr ) { } template Binary_search_tree::~Binary_search_tree() { clear(); } template Binary_search_node *Binary_search_tree::root() const { return root_node; } template bool Binary_search_tree::empty() const { return root() == nullptr; } template int Binary_search_tree::size() const { if ( root() == nullptr ) { return 0; } std::stack< Binary_search_node * > depth_stack; int tree_size = 0; depth_stack.push( root() ); while( !depth_stack.empty() ) { Binary_search_node *ptr = depth_stack.top(); depth_stack.pop(); ++tree_size; if ( ptr->right() != nullptr ) { depth_stack.push( ptr->right() ); } if ( ptr->left() != nullptr ) { depth_stack.push( ptr->left() ); } } return tree_size; } template int Binary_search_tree::height() const { if ( root() == nullptr ) { return -1; } std::stack< Binary_search_node * > depth_stack; Binary_search_node *last_popped = nullptr; depth_stack.push( root() ); int depth = 0; while ( depth_stack.top()->left() != nullptr ) { depth_stack.push( depth_stack.top()->left() ); ++depth; } int height = depth; while( !depth_stack.empty() ) { if ( depth_stack.top()->right() != nullptr && depth_stack.top()->right() != last_popped ) { depth_stack.push( depth_stack.top()->right() ); ++depth; height = std::max( height, depth ); while ( depth_stack.top()->left() != nullptr ) { depth_stack.push( depth_stack.top()->left() ); ++depth; height = std::max( height, depth ); } } else { last_popped = depth_stack.top(); depth_stack.pop(); --depth; } } return height; } template Type Binary_search_tree::front() const { if ( empty() ) { throw underflow(); } Binary_search_node *ptr = root(); while ( ptr->left() != nullptr ) { ptr = ptr->left(); } return ptr->retrieve(); } template Type Binary_search_tree::back() const { if ( empty() ) { throw underflow(); } Binary_search_node *ptr = root(); while ( ptr->right() != nullptr ) { ptr = ptr->right(); } return ptr->retrieve(); } template bool Binary_search_tree::find( Type const &obj ) const { if ( empty() ) { throw underflow(); } Binary_search_node *current = root(); while ( true ) { if ( current->retrieve() == obj ) { return true; } else if ( current->retrieve() > obj ) { if ( current->left() == nullptr ) { return false; } else { current = current->left(); } } else { if ( current->right() == nullptr ) { return false; } else { current = current->right(); } } } } template void Binary_search_tree::clear() { if ( root() == nullptr ) { return; } std::stack< Binary_search_node * > depth_stack; depth_stack.push( root() ); while( !depth_stack.empty() ) { Binary_search_node *ptr = depth_stack.top(); depth_stack.pop(); if ( ptr->right() != nullptr ) { depth_stack.push( ptr->right() ); } if ( ptr->left() != nullptr ) { depth_stack.push( ptr->left() ); } delete ptr; } } template bool Binary_search_tree::insert( Type const &obj ) { if ( empty() ) { root_node = new Binary_search_node( obj ); return true; } Binary_search_node *current = root(); while ( true ) { if ( current->retrieve() == obj ) { return false; } if ( current->retrieve() > obj ) { if ( current->left() == nullptr ) { current->left_tree = new Binary_search_node( obj ); return true; } else { current = current->left(); } } else { if ( current->right() == nullptr ) { current->right_tree = new Binary_search_node( obj ); return true; } else { current = current->right(); } } } } template bool Binary_search_tree::erase( Type const &obj ) { if ( empty() ) { return false; } if ( root()->retrieve() == obj ) { if ( root()->left() == nullptr && root()->right() == nullptr ) { root_node = nullptr; delete root(); } else if ( root()->left() == nullptr ) { Binary_search_node *tmp = root(); root_node = root()->right(); delete tmp; } else if ( root()->right() == nullptr ) { Binary_search_node *tmp = root(); root_node = root()->left(); delete tmp; } else { if ( root()->right()->left() == nullptr ) { root()->element = root()->right()->retrieve(); Binary_search_node *tmp = root()->right(); root()->right_tree = root()->right()->right(); delete tmp; } else { Binary_search_node *ptr = root()->right(); Binary_search_node *parent; while ( ptr->left() != nullptr ) { parent = ptr; ptr = ptr->left(); } root()->element = ptr->retrieve(); if ( ptr->right() == nullptr ) { parent->left_tree = nullptr; } else { parent->left_tree = ptr->right(); } delete ptr; } } return true; } Binary_search_node *current = root(); Binary_search_node *parent; bool is_left_subtree; while ( true ) { if ( current->retrieve() == obj ) { break; } else if ( current->retrieve() > obj ) { if ( current->left() == nullptr ) { return false; } else { parent = current; current = current->left(); is_left_subtree = true; } } else { if ( current->right() == nullptr ) { return false; } else { parent = current; current = current->right(); is_left_subtree = false; } } } if ( current->left() == nullptr && current->right() == nullptr ) { if ( is_left_subtree ) { parent->left_tree = nullptr; } else { parent->right_tree = nullptr; } delete current; } else if ( current->left() == nullptr ) { if ( is_left_subtree ) { parent->left_tree = current->right(); } else { parent->right_tree = current->right(); } delete current; } else if ( current->right() == nullptr ) { if ( is_left_subtree ) { parent->left_tree = current->left(); } else { parent->right_tree = current->left(); } delete current; } else { if ( current->right()->left() == nullptr ) { current->element = current->right()->retrieve(); Binary_search_node *tmp = current->right(); current->right_tree = current->right()->right(); delete tmp; } else { Binary_search_node *ptr = current->right(); while ( ptr->left() != nullptr ) { parent = ptr; ptr = ptr->left(); } current->element = ptr->retrieve(); if ( ptr->right() == nullptr ) { parent->left_tree = nullptr; } else { parent->left_tree = ptr->right(); } delete ptr; } } return true; } #endif