#include"BST.h"
#include<iostream>
#include<stdbool.h>
#include<time.h>
using namespace std;
#pragma once
template<typename T> class Splay :public BST<T>
{
protected:
bin_node_posi<T> splay(bin_node_posi<T> v)
{
if (v == this->root) return v;
bin_node_posi<T> p; bin_node_posi<T> g;
while ((p = v->parent) && (g = p->parent))
{
bin_node_posi<T> gg = g->parent;
bin_node_posi<T>& to_g = FROM_PARENT_TO(*g);
if (IS_LCHILD(*v))
if (IS_LCHILD(*p)) {
attach_as_lchild(p->rchild, g);
attach_as_lchild(v->rchild, p);
attach_as_rchild(v, p);
attach_as_rchild(p, g);
}
else {
attach_as_lchild(v->rchild, p);
attach_as_rchild(g, v->lchild);
attach_as_lchild(g, v);
attach_as_rchild(v, p);
}
else
if (IS_RCHILD(*p))
{
attach_as_rchild(g, p->lchild);
attach_as_rchild(p, v->lchild);
attach_as_lchild(g, p);
attach_as_lchild(p, v);
}
else {
attach_as_rchild(p, v->lchild);
attach_as_lchild(v->rchild, g);
attach_as_lchild(p, v);
attach_as_rchild(v, g);
}
if (gg == nullptr) v->parent = nullptr;
else {
to_g = v; v->parent = gg;
}
this->update_height(g); this->update_height(p); this->update_height(v);
}
if (v->parent == this->root)
{
if (IS_LCHILD(*v)) {
attach_as_lchild(v->rchild, p);
attach_as_rchild(v, p);
}
else {
attach_as_rchild(p, v->lchild);
attach_as_lchild(p, v);
}
v->parent = nullptr;
this->update_height(p); this->update_height(v);
}
return v;
}
public:
bin_node_posi<T>& search(const T& e);
bin_node_posi<T> insert(const T& e);
bool remove(const T& e);
void inline attach_as_rchild(bin_node_posi<T> p, bin_node_posi<T> v)
{
p->rchild = v; if (v) v->parent = p;
}
void inline attach_as_lchild(bin_node_posi<T> v, bin_node_posi<T> p)
{
p->lchild = v; if (v) v->parent = p;
}
};
template<typename T> bin_node_posi<T>& Splay<T>::search(const T& e)
{
bin_node_posi<T> searched = BST<T>::search(e);
this->root = splay(searched ? searched : this->phit);
return this->root;
}
template<typename T> bin_node_posi<T> Splay<T>::insert(const T& e)
{
bin_node_posi<T> ptr = search(e);
bin_node_posi<T> temp = new bin_node<T>(e);
if (ptr == nullptr) {
this->root = temp;
return this->root;
}
if (e == ptr->data) return this->root;
if (e > this->root->data)
{
this->root->parent = temp;
temp->lchild = this->root;
bin_node_posi<T> rtree = this->root->rchild;
this->root->rchild = nullptr;
if (rtree) rtree->parent = nullptr;
temp->rchild = rtree;
if (rtree != nullptr) rtree->parent = temp;
}
else {
this->root->parent = temp;
temp->rchild = this->root;
bin_node_posi<T> ltree = this->root->lchild;
this->root->lchild = nullptr;
if (ltree) ltree->parent = nullptr;
temp->lchild = ltree;
if (ltree != nullptr) ltree->parent = temp;
}
this->root = temp;
this->update_height_above(ptr);
return this->root;
}
template<typename T> bool Splay<T>::remove(const T& e)
{
bin_node_posi<T> ptr = search(e);
if (ptr == nullptr || ptr->data != e) return false;
if (!HAS_LCHILD(*this->root))
{
this->root = this->root->rchild;
if (this->root) this->root->parent = nullptr;
}
else if (!HAS_RCHILD(*this->root))
{
this->root = this->root->lchild;
if (this->root) this->root->parent = nullptr;
}
else {
bin_node_posi<T> ltree = this->root->lchild;
bin_node_posi<T> rtree = this->root->rchild;
this->root->lchild = nullptr;
this->root->rchild = nullptr;
ltree->parent = nullptr;
rtree->parent = nullptr;
this->root = rtree;
search(e);
ltree->parent = this->root;
this->root->lchild = ltree;
}
if (this->root) this->update_height(this->root);
release(ptr->data);
release(ptr);
return true;
}
int main()
{
srand((unsigned)time(nullptr));
Splay<int> splay;
Visit<int> visit;
for (int i = 0; i < 20; ++i)
{
int num = i + rand() % 32;
cout << num << " ";
splay.insert(num);
}
cout << endl;
splay.inorder_tra(visit);
for (int i = 0; i < 10; i++)
{
int num = rand() % 32 + 1;
cout << endl << "the num to remove is : " << num << endl;
splay.remove(num);
splay.inorder_tra(visit);
}
}
