#include #include #include #include #include #include template struct Node; template using Node_ptr = std::unique_ptr>; template struct Node{ T value; int max_depth; int inbalance; 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}, inbalance{0}, small{nullptr}, big{nullptr}{} }; template class Tree{ Node_ptr root; Node_ptr* find(T val); bool try_to_del(Node_ptr* node, T val); bool try_to_add(Node_ptr* node, T val); void rotate_left(Node_ptr* root); void rotate_right(Node_ptr* root); void balance(Node_ptr* n); bool test_insert(); bool test_del(); bool test_depth(Node_ptr* n); public: bool insert(T val); bool del(T val); void print() const; bool test(); }; template Node_ptr* Tree::find(T val){ for(Node_ptr* n = &root; *n;){ if(val == (*n)->value) return n; else if(val < (*n)->value) n = &(*n)->small; else n = &(*n)->big; } return nullptr; } template bool Tree::insert(T val){ return try_to_add(&root, val); } template bool Tree::try_to_add(Node_ptr* node, T val){ if( ! (*node)){ *node = std::make_unique>(val); (*node)->update_depth(); balance(node); return true; } else{ if (val == (*node)->value) return false; else if(val < (*node)->value){ if( ! try_to_add( &(*node)->small, val)) return false; } else{//(val > (*node)->value) if( ! try_to_add( &(*node)->big, val)) return false; } (*node)->update_depth(); balance(node); return true; } } 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_ptr* temp = node; std::vector*> path; if((*node)->small) { path.push_back(temp); temp = &(*node)->small; } else { node->reset((*node)->big.release()); return true; } while((*temp)->big){ path.push_back(temp); temp = &(*temp)->big; } //mam temp na 'to swap' nodu... std::swap((*node)->value, (*temp)->value); temp->reset((*temp)->small.release()); 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(); balance(node); return true; } return false; } } else { if( ! (*node)->big) return false; else { if(try_to_del(&(*node)->big, val)){ (*node)->update_depth(); balance(node); return true; } return false; } } } template void Tree::rotate_left(Node_ptr* root){ Node* new_root = (*root)->big.release(); std::swap((*root)->big, new_root->small); new_root->small.reset(root->release()); root->reset(new_root); if((*root)->small) (*root)->small->update_depth(); (*root)->update_depth(); } template void Tree::rotate_right(Node_ptr* root){ Node* new_root = (*root)->small.release(); std::swap((*root)->small, new_root->big); new_root->big.reset(root->release()); root->reset(new_root); if( (*root)->big) (*root)->big->update_depth(); (*root)->update_depth(); } template void Tree::balance(Node_ptr* n){ if((*n)->inbalance >= -1 && (*n)->inbalance <= 1) return; else if ((*n)->inbalance > 1){ if((*n)->big && (*n)->big->inbalance == -1) rotate_right(&(*n)->big) ; rotate_left(n) ; } else{ if((*n)->small && (*n)->small->inbalance == 1) rotate_left(&(*n)->small); rotate_right(n) ; } } template void Tree::print() const { std::ofstream ofs; ofs.open("viz.dot"); ofs << "digraph Tree {\n"; if(root) root->dump(ofs); ofs << "}"; ofs.close(); system("cat viz.dot | dot -Tx11"); } template bool Tree::test(){ //vect s opak cisly, zkusim vlozit do stromu i setu a porovnam success, zkontroluju hloubky root.reset(); bool ins = test_insert(); bool depth = test_depth(&root); bool del = test_del(); std::cout << "--- INSERTING ---" << "\n"; if(ins) std::cout << "\033[92m" << "\t\t" << "... done" << "\033[0m" << "\n"; else std::cout << "\033[91m" << "\t\t" << "... wrong" << "\033[0m" << "\n"; std::cout << "--- CHECKING DEPTHS ---" << "\n"; if(depth) std::cout << "\033[92m" << "\t\t" << "... done" << "\033[0m" << "\n"; else std::cout << "\033[91m" << "\t\t" << "... wrong" << "\033[0m" << "\n"; std::cout << "--- EREASING ---" << "\n"; if(del) std::cout << "\033[92m" << "\t\t" << "... done" << "\033[0m" << "\n"; else std::cout << "\033[91m" << "\t\t" << "... wrong" << "\033[0m" << "\n"; root.reset(); return ins && depth && del; } template bool Tree::test_insert(){ root.reset(); std::vector vec; for(int i = 0; i < 10000000; i++){ srand(i*3); vec.push_back((rand() % 20000) - 9999); } std::set set; size_t prev_set_size = 0; bool tree_ins; // std::cout << "--- FILLING UP ---\n"; for(int i = 0; i < 10000000; i++){ set.insert(vec[i]); tree_ins = insert(vec[i]); if(tree_ins && set.size() == prev_set_size){ // std::cout << "falsely inserted! \n"; return false; } else if(!tree_ins && set.size() != prev_set_size){ // std::cout << "skipped insert! \n"; return false; } else prev_set_size = set.size(); } return true; } template bool Tree::test_del(){ root.reset(); std::vector vec; std::set set; for(int i = 0; i < 10000000; i++){ srand(10000000-i); vec.push_back((rand() % 20000) - 9999); set.insert ((rand() % 20000) - 9999); insert ((rand() % 20000) - 9999); } bool set_del; bool tree_del; // std::cout << "--- EMPTYING ---\n"; for(int i = 0; i < 10000000; i++){ tree_del = del(vec[i]); set_del = set.erase(vec[i]); if(tree_del && !set_del){ // std::cout << "falsely deleted! \n"; return false; } if(!tree_del && set_del){ // std::cout << "skipped delete! \n"; return false; } } return true; } template bool Tree::test_depth(Node_ptr* n){ if((*n)->small && (*n)->big){ return test_depth(&(*n)->small) && test_depth(&(*n)->big) && (*n)->max_depth == ( std::max((*n)->small->max_depth, (*n)->big->max_depth) + 1 ); } else if((*n)->small){ return test_depth(&(*n)->small) && (*n)->max_depth == (*n)->small->max_depth + 1; } else if((*n)->big){ return test_depth(&(*n)->big) && (*n)->max_depth == (*n)->big->max_depth + 1; } else{ return (*n)->max_depth == 0; } } template void Node::update_depth(){ if (small && big) { max_depth = std::max(small->max_depth, big->max_depth) + 1; inbalance = big->max_depth - small->max_depth; } else if (small) { max_depth = small->max_depth + 1; inbalance = - small->max_depth - 1; } else if (big) { max_depth = big->max_depth + 1; inbalance = big->max_depth + 1; } else { max_depth = 0; inbalance = 0; } } template void Node::dump(std::ofstream& ofs) const { if (small) { ofs << '"' << value << " : " << inbalance << '"' << " -> " << '"' << small->value << " : " << small->inbalance << '"' << '\n'; small->dump(ofs); } if (big) { ofs << '"' << value << " : " << inbalance << '"' << " -> " << '"' << big->value << " : " << big->inbalance << '"' << '\n'; big->dump(ofs); } } int main(){ Tree t; bool test = t.test(); if(!test) std::cout << "You're stupid!" << "\n"; // std::vector v = {9, 2, 5, 7, 4, 8, -1, 15, 12, 17, 10, 13}; // std::cout << "\t" << "toto je odsazene"<< "\n"; // for(auto i : v){ // if(t.insert(i)) std::cout << "added " << i << "\n"; // else std::cout << "failed at adding " << i << "\n"; // t.print(); // } // for(auto i : v){ // if(t.del(i)) std::cout << "deleted " << i << "\n"; // else std::cout << "failed at deleting " << i << "\n"; // t.print(); // } }