balance
This commit is contained in:
parent
b82c258399
commit
e3a84c82a3
257
tree.cpp
257
tree.cpp
|
@ -1,7 +1,9 @@
|
||||||
#include<fstream>
|
#include<fstream>
|
||||||
#include<iostream>
|
#include<iostream>
|
||||||
#include<vector>
|
#include<vector>
|
||||||
|
#include<set>
|
||||||
#include<memory>
|
#include<memory>
|
||||||
|
#include<cstdlib>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Node;
|
struct Node;
|
||||||
|
@ -13,6 +15,7 @@ template <typename T>
|
||||||
struct Node{
|
struct Node{
|
||||||
T value;
|
T value;
|
||||||
int max_depth;
|
int max_depth;
|
||||||
|
int inbalance;
|
||||||
Node_ptr<T> small;
|
Node_ptr<T> small;
|
||||||
Node_ptr<T> big;
|
Node_ptr<T> big;
|
||||||
|
|
||||||
|
@ -20,19 +23,32 @@ struct Node{
|
||||||
bool add_to_child(Node_ptr<T>* child, T val);
|
bool add_to_child(Node_ptr<T>* child, T val);
|
||||||
void update_depth();
|
void update_depth();
|
||||||
void dump(std::ofstream& ofs) const;
|
void dump(std::ofstream& ofs) const;
|
||||||
Node(T v): value{v}, max_depth{0}, small{nullptr}, big{nullptr}{}
|
Node(T v): value{v}, max_depth{0}, inbalance{0}, small{nullptr}, big{nullptr}{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Tree{
|
class Tree{
|
||||||
Node_ptr<T> root;
|
Node_ptr<T> root;
|
||||||
|
|
||||||
Node_ptr<T>* find(T val);
|
Node_ptr<T>* find(T val);
|
||||||
bool try_to_del(Node_ptr<T>* node, T val);
|
bool try_to_del(Node_ptr<T>* node, T val);
|
||||||
|
bool try_to_add(Node_ptr<T>* node, T val);
|
||||||
|
void rotate_left(Node_ptr<T>* root);
|
||||||
|
void rotate_right(Node_ptr<T>* root);
|
||||||
|
void balance(Node_ptr<T>* n);
|
||||||
|
|
||||||
|
bool test_insert();
|
||||||
|
bool test_del();
|
||||||
|
bool test_depth(Node_ptr<T>* n);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool insert(T val);
|
bool insert(T val);
|
||||||
bool del(T val);
|
bool del(T val);
|
||||||
void print() const;
|
void print() const;
|
||||||
|
bool test();
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -47,37 +63,31 @@ Node_ptr<T>* Tree<T>::find(T val){
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool Tree<T>::insert(T val){
|
bool Tree<T>::insert(T val){
|
||||||
if(!root){
|
return try_to_add(&root, val);
|
||||||
root = std::make_unique<Node<T>>(val);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else return root->add(val);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool Node<T>::add(T val){
|
bool Tree<T>::try_to_add(Node_ptr<T>* node, T val){
|
||||||
if (val == value) return false;
|
if( ! (*node)){
|
||||||
else if (val < value) return add_to_child(&small, val);
|
*node = std::make_unique<Node<T>>(val);
|
||||||
else return add_to_child(&big, val);
|
(*node)->update_depth();
|
||||||
}
|
balance(node);
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool Node<T>::add_to_child(Node_ptr<T>* child, T val){
|
|
||||||
if(!(*child)){
|
|
||||||
*child = std::make_unique<Node<T>>(val);
|
|
||||||
update_depth();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
if((*child)->add(val)){
|
if (val == (*node)->value) return false;
|
||||||
update_depth();
|
else if(val < (*node)->value){
|
||||||
return true;
|
if( ! try_to_add( &(*node)->small, val)) return false;
|
||||||
}
|
}
|
||||||
return false;
|
else{//(val > (*node)->value)
|
||||||
|
if( ! try_to_add( &(*node)->big, val)) return false;
|
||||||
|
}
|
||||||
|
(*node)->update_depth();
|
||||||
|
balance(node);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool Tree<T>::del(T val){
|
bool Tree<T>::del(T val){
|
||||||
if(!root) return false;
|
if(!root) return false;
|
||||||
|
@ -91,7 +101,6 @@ bool Tree<T>::try_to_del(Node_ptr<T>* node, T val){
|
||||||
std::vector<Node_ptr<T>*> path;
|
std::vector<Node_ptr<T>*> path;
|
||||||
if((*node)->small) {
|
if((*node)->small) {
|
||||||
path.push_back(temp);
|
path.push_back(temp);
|
||||||
std::cout << "pushing " << (*temp)->value << "\n";
|
|
||||||
temp = &(*node)->small;
|
temp = &(*node)->small;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -100,7 +109,6 @@ bool Tree<T>::try_to_del(Node_ptr<T>* node, T val){
|
||||||
}
|
}
|
||||||
while((*temp)->big){
|
while((*temp)->big){
|
||||||
path.push_back(temp);
|
path.push_back(temp);
|
||||||
std::cout << "pushing " << (*temp)->value << "\n";
|
|
||||||
temp = &(*temp)->big;
|
temp = &(*temp)->big;
|
||||||
}
|
}
|
||||||
//mam temp na 'to swap' nodu...
|
//mam temp na 'to swap' nodu...
|
||||||
|
@ -115,6 +123,7 @@ bool Tree<T>::try_to_del(Node_ptr<T>* node, T val){
|
||||||
else {
|
else {
|
||||||
if(try_to_del(&(*node)->small, val)){
|
if(try_to_del(&(*node)->small, val)){
|
||||||
(*node)->update_depth();
|
(*node)->update_depth();
|
||||||
|
balance(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -125,6 +134,7 @@ bool Tree<T>::try_to_del(Node_ptr<T>* node, T val){
|
||||||
else {
|
else {
|
||||||
if(try_to_del(&(*node)->big, val)){
|
if(try_to_del(&(*node)->big, val)){
|
||||||
(*node)->update_depth();
|
(*node)->update_depth();
|
||||||
|
balance(node);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -133,22 +143,37 @@ bool Tree<T>::try_to_del(Node_ptr<T>* node, T val){
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void Node<T>::update_depth(){
|
void Tree<T>::rotate_left(Node_ptr<T>* root){
|
||||||
if(small && big) max_depth = std::max(small->max_depth, big->max_depth) + 1;
|
Node<T>* new_root = (*root)->big.release();
|
||||||
else if (small) max_depth = small->max_depth + 1;
|
std::swap((*root)->big, new_root->small);
|
||||||
else if (big) max_depth = big->max_depth + 1;
|
new_root->small.reset(root->release());
|
||||||
else max_depth = 0;
|
root->reset(new_root);
|
||||||
|
|
||||||
|
if((*root)->small) (*root)->small->update_depth();
|
||||||
|
(*root)->update_depth();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void Node<T>::dump(std::ofstream& ofs) const {
|
void Tree<T>::rotate_right(Node_ptr<T>* root){
|
||||||
if (small) {
|
Node<T>* new_root = (*root)->small.release();
|
||||||
ofs << '"' << value << " : " << max_depth << '"' << " -> " << '"' << small->value << " : " << small->max_depth << '"' << '\n';
|
std::swap((*root)->small, new_root->big);
|
||||||
small->dump(ofs);
|
new_root->big.reset(root->release());
|
||||||
|
root->reset(new_root);
|
||||||
|
|
||||||
|
if( (*root)->big) (*root)->big->update_depth();
|
||||||
|
(*root)->update_depth();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void Tree<T>::balance(Node_ptr<T>* 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) ;
|
||||||
}
|
}
|
||||||
if (big) {
|
else{
|
||||||
ofs << '"' << value << " : " << max_depth << '"' << " -> " << '"' << big->value << " : " << big->max_depth << '"' << '\n';
|
if((*n)->small && (*n)->small->inbalance == 1) rotate_left(&(*n)->small);
|
||||||
big->dump(ofs);
|
rotate_right(n) ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,17 +189,155 @@ void Tree<T>::print() const {
|
||||||
system("cat viz.dot | dot -Tx11");
|
system("cat viz.dot | dot -Tx11");
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(){
|
template <typename T>
|
||||||
Tree<int> t;
|
bool Tree<T>::test(){
|
||||||
std::vector<int> v = {9, 2, 5, 7, 4, 8, -1, 15, 12, 17, 10, 13};
|
//vect s opak cisly, zkusim vlozit do stromu i setu a porovnam success, zkontroluju hloubky
|
||||||
for(auto i : v){
|
root.reset();
|
||||||
if(t.insert(i)) std::cout << "added " << i << "\n";
|
bool ins = test_insert();
|
||||||
else std::cout << "failed at adding " << i << "\n";
|
bool depth = test_depth(&root);
|
||||||
t.print();
|
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 <typename T>
|
||||||
|
bool Tree<T>::test_insert(){
|
||||||
|
root.reset();
|
||||||
|
std::vector<int> vec;
|
||||||
|
for(int i = 0; i < 10000000; i++){
|
||||||
|
srand(i*3);
|
||||||
|
vec.push_back((rand() % 20000) - 9999);
|
||||||
}
|
}
|
||||||
for(auto i : v){
|
|
||||||
if(t.del(i)) std::cout << "deleted " << i << "\n";
|
std::set<int> set;
|
||||||
else std::cout << "failed at deleting " << i << "\n";
|
size_t prev_set_size = 0;
|
||||||
t.print();
|
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 <typename T>
|
||||||
|
bool Tree<T>::test_del(){
|
||||||
|
root.reset();
|
||||||
|
std::vector<int> vec;
|
||||||
|
std::set<int> 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 <typename T>
|
||||||
|
bool Tree<T>::test_depth(Node_ptr<T>* 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 <typename T>
|
||||||
|
void Node<T>::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 <typename T>
|
||||||
|
void Node<T>::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<int> t;
|
||||||
|
bool test = t.test();
|
||||||
|
if(!test) std::cout << "You're stupid!" << "\n";
|
||||||
|
// std::vector<int> 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();
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue