diff --git a/tree.cpp b/tree.cpp index 96453d2..0c43c17 100644 --- a/tree.cpp +++ b/tree.cpp @@ -12,16 +12,22 @@ using Node_ptr = std::unique_ptr>; template struct Node{ T value; + int max_depth; Node_ptr small; Node_ptr big; + + bool add(T val); + bool add_to_child(Node_ptr* child, T val); + void update_depth(); void dump(std::ofstream& ofs) const; + Node(T v): value{v}, max_depth{0}, small{nullptr}, big{nullptr}{} }; template class Tree{ Node_ptr root; Node_ptr* find(T val); - Node_ptr* find_to_swap(Node_ptr* unwanted); + bool try_to_del(Node_ptr* node, T val); public: bool insert(T val); @@ -39,69 +45,106 @@ Node_ptr* Tree::find(T val){ return nullptr; } -template -Node_ptr* Tree::find_to_swap(Node_ptr* unwanted){ - if((*unwanted)->small) unwanted = &(*unwanted)->small; - else return nullptr; - while((*unwanted)->big) unwanted = &(*unwanted)->big; - return unwanted; -} - -template -bool Tree::del(T val){ - Node_ptr* unwanted = find(val); - if(!unwanted) return false; - Node_ptr* to_swap = find_to_swap(unwanted); - if(!to_swap){ - (*unwanted).reset((*unwanted)->big.release()); - } - else{ - std::swap((*unwanted)->value, (*to_swap)->value); - (*to_swap).reset((*to_swap)->small.release()); - } - return true; -} - template bool Tree::insert(T val){ - std::unique_ptr> node = std::make_unique>(); - node->value = val; - if (!root){ - root.swap(node); + if(!root){ + root = std::make_unique>(val); + return true; + } + else return root->add(val); +} + +template +bool Node::add(T val){ + if (val == value) return false; + else if (val < value) return add_to_child(&small, val); + else return add_to_child(&big, val); +} + +template +bool Node::add_to_child(Node_ptr* child, T val){ + if(!(*child)){ + *child = std::make_unique>(val); + update_depth(); return true; } else{ - Node* temp = root.get(); - while(temp){ - if(val < temp->value){ - if(temp->small) temp = temp->small.get(); - else{ - temp->small.swap(node); - return true; - } - } - else if(val > temp->value){ - if(temp->big) temp = temp->big.get(); - else{ - temp->big.swap(node); - return true; - } - } - else return false; + if((*child)->add(val)){ + update_depth(); + return true; } return false; } } +template +bool Tree::del(T val){ + if(!root) return false; + else return try_to_del(&root, val); +} + +template +bool Tree::try_to_del(Node_ptr* node, T val){ + if(val == (*node)->value) { + Node* temp = (*node).get(); + std::vector*> path; + if((*node)->small) { + temp = (*node)->small.get(); + path.push_back(temp); + } + else { + node->reset((*node)->big.release()); + return true; + } + while(temp->big){ + temp = temp->big.get(); + path.push_back(temp); + } + //mam temp na 'to swap' nodu... + std::swap((*node)->value, temp->value); + //temp->steal_values(std::move(temp->small)); + for(int i = path.size() -1; i >= 0; i--) path[i]->update_depth(); + path.clear(); + return true; + } + else if(val < (*node)->value){ + if(!(*node)->small) return false; + else { + if(try_to_del(&(*node)->small, val)){ + (*node)->update_depth(); + return true; + } + return false; + } + } + else { + if(!(*node)->big) return false; + else { + if(try_to_del(&(*node)->big, val)){ + (*node)->update_depth(); + return true; + } + return false; + } + } +} + +template +void Node::update_depth(){ + if(small && big) max_depth = std::max(small->max_depth, big->max_depth) + 1; + else if (small) max_depth = small->max_depth + 1; + else max_depth = big->max_depth + 1; +} + template void Node::dump(std::ofstream& ofs) const { if (small) { - ofs << value << " -> " << small->value << '\n'; + ofs << '"' << value << " : " << max_depth << '"' << " -> " << '"' << small->value << " : " << small->max_depth << '"' << '\n'; small->dump(ofs); } if (big) { - ofs << value << " -> " << big->value << '\n'; + ofs << '"' << value << " : " << max_depth << '"' << " -> " << '"' << big->value << " : " << big->max_depth << '"' << '\n'; big->dump(ofs); } } @@ -120,7 +163,7 @@ void Tree::print() const { int main(){ Tree t; - std::vector v = {3, 6, 8, -1, 7, 0, 9, 2, -11, 5}; + std::vector v = {3, 6, 8}; for(auto i : v){ if(t.insert(i)) std::cout << "added " << i << "\n"; else std::cout << "failed at adding " << i << "\n";