134 lines
3.1 KiB
C++
134 lines
3.1 KiB
C++
#include<fstream>
|
|
#include<iostream>
|
|
#include<vector>
|
|
#include<memory>
|
|
|
|
template <typename T>
|
|
struct Node;
|
|
|
|
template <typename T>
|
|
using Node_ptr = std::unique_ptr<Node<T>>;
|
|
|
|
template <typename T>
|
|
struct Node{
|
|
T value;
|
|
Node_ptr<T> small;
|
|
Node_ptr<T> big;
|
|
void dump(std::ofstream& ofs) const;
|
|
};
|
|
|
|
template <typename T>
|
|
class Tree{
|
|
Node_ptr<T> root;
|
|
Node_ptr<T>* find(T val);
|
|
Node_ptr<T>* find_to_swap(Node_ptr<T>* unwanted);
|
|
|
|
public:
|
|
bool insert(T val);
|
|
bool del(T val);
|
|
void print() const;
|
|
};
|
|
|
|
template <typename T>
|
|
Node_ptr<T>* Tree<T>::find(T val){
|
|
for(Node_ptr<T>* n = &root; *n;){
|
|
if(val == (*n)->value) return n;
|
|
else if(val < (*n)->value) n = &(*n)->small;
|
|
else n = &(*n)->big;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
template <typename T>
|
|
Node_ptr<T>* Tree<T>::find_to_swap(Node_ptr<T>* unwanted){
|
|
if((*unwanted)->small) unwanted = &(*unwanted)->small;
|
|
else return nullptr;
|
|
while((*unwanted)->big) unwanted = &(*unwanted)->big;
|
|
return unwanted;
|
|
}
|
|
|
|
template <typename T>
|
|
bool Tree<T>::del(T val){
|
|
Node_ptr<T>* unwanted = find(val);
|
|
if(!unwanted) return false;
|
|
Node_ptr<T>* 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 <typename T>
|
|
bool Tree<T>::insert(T val){
|
|
std::unique_ptr<Node<T>> node = std::make_unique<Node<T>>();
|
|
node->value = val;
|
|
if (!root){
|
|
root.swap(node);
|
|
return true;
|
|
}
|
|
else{
|
|
Node<T>* 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;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
void Node<T>::dump(std::ofstream& ofs) const {
|
|
if (small) {
|
|
ofs << value << " -> " << small->value << '\n';
|
|
small->dump(ofs);
|
|
}
|
|
if (big) {
|
|
ofs << value << " -> " << big->value << '\n';
|
|
big->dump(ofs);
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
void Tree<T>::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");
|
|
}
|
|
|
|
int main(){
|
|
Tree<int> t;
|
|
std::vector<int> v = {3, 6, 8, -1, 7, 0, 9, 2, -11, 5};
|
|
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();
|
|
}
|
|
} |