スプレイ木とは
- SleatorとTarjanによって紹介
- 自己調整を行う平衡二分探索木
- アクセスした頂点がルートにくるように「スプレイ操作」を繰り返し行う
- 頂点へのアクセスに偏りがある場合に有効(ある頂点によくアクセスするなど)
- スプレイ操作
- zig
- ある頂点xの親頂点p(x)がルートならば、頂点xと親頂点p(x)の辺をつなぎかえる
- zig-zig
- 親頂点p(x)がルートでなく、頂点xも親頂点p(x)も左側(または右側)の場合、親頂点p(x)と親頂点p(x)の親頂点g(x)について辺をつなぎかえ、次にxとp(x)について辺をつなぎかえる
- zig-zag
- 親頂点p(x)がルートでなく、頂点xが左側の子で親頂点が右側の子(またはその逆)のとき、xとp(x)の辺をつなぎかえ、次にxと新たなp(x)の辺をつなぎかえる
スプレイ木の実装
- Spaghetti Sourceを少し自分の使いやすいように直した
- 論文中のsimple top-down splayによる実装
#include <iostream>
template<class T>
class splay_tree {
struct node {
T key;
node *l, *r;
node(T k, node *l = 0, node *r = 0):key(k), l(l), r(r){ }
};
node *root;
node* splay(T x, node *t){
if(!t) return t;
node N(x);
node *l = &N, *r = &N;
node *s;
while(true){
if(x < t->key){
if(t->l && x < t->l->key){
s = t->l;
t->l = s->r;
s->r = t;
t = s;
}
if(!t->l) break;
r->l = t;
r = t;
t = t->l;
}else if(x > t->key){
if(t->r && x > t->r->key){
s = t->r;
t->r = s->l;
s->l = t;
t = s;
}
if(!t->r) break;
l->r = t;
l = t;
t = t->r;
}else break;
}
l->r = t->l;
r->l = t->r;
t->l = N.r;
t->r = N.l;
return t;
}
void delete_subtree(node *t){
if(!t) return;
delete_subtree(t->l);
delete_subtree(t->r);
delete t;
}
public:
bool find(T x){
if(!root) return false;
root = splay(x, root);
if(x == root->key) return true;
return false;
}
void insert(T x){
if(!root) root = new node(x);
else{
root = splay(x, root);
if(x < root->key){
node *t = new node(x, root->l, root);
root->l = 0;
root = t;
}else if(x > root->key){
node *t = new node(x, root, root->r);
root->r = 0;
root = t;
}
}
}
void erase(T x){
if(!find(x)) return;
if(!root->l){
root = root->r;
}else{
node *t = root->r;
root = splay(x, root->l);
root->r = t;
}
}
splay_tree(): root(0){ }
~splay_tree(){
delete_subtree(root);
}
};
void print_result(splay_tree<int> &st, int v){
if(st.find(v)){
std::cout << v << " find" << std::endl;
}else{
std::cout << v << " not find" << std::endl;
}
}
int main(){
splay_tree<int> st;
st.insert(3);
st.insert(4);
st.insert(6);
st.insert(5);
st.insert(7);
st.insert(2);
print_result(st, 1);
print_result(st, 3);
print_result(st, 5);
print_result(st, 7);
print_result(st, 9);
return 0;
}