use obj_pool::{ObjId, ObjPool};
struct Node<T> {
parent: Option<ObjId>,
children: [Option<ObjId>; 2],
value: T,
}
impl<T> Node<T> {
fn new(value: T) -> Node<T> {
Node {
parent: None,
children: [None, None],
value,
}
}
}
struct Splay<T> {
obj_pool: ObjPool<Node<T>>,
root: Option<ObjId>,
}
impl<T> Splay<T>
where
T: Ord,
{
fn new() -> Splay<T> {
Splay {
obj_pool: ObjPool::new(),
root: None,
}
}
#[inline(always)]
fn link(&mut self, p: ObjId, c: Option<ObjId>, dir: usize) {
self.obj_pool[p].children[dir] = c;
if let Some(c) = c {
self.obj_pool[c].parent = Some(p);
}
}
#[inline(always)]
fn rotate(&mut self, p: ObjId, c: ObjId) {
let g = self.obj_pool[p].parent;
let dir = if self.obj_pool[p].children[0] == Some(c) {
0
} else {
1
};
let t = self.obj_pool[c].children[dir ^ 1];
self.link(p, t, dir);
self.link(c, Some(p), dir ^ 1);
if let Some(g) = g {
let dir = if self.obj_pool[g].children[0] == Some(p) {
0
} else {
1
};
self.link(g, Some(c), dir);
} else {
self.root = Some(c);
self.obj_pool[c].parent = None;
}
}
fn splay(&mut self, c: ObjId) {
while let Some(p) = self.obj_pool[c].parent {
let Some(g) = self.obj_pool[p].parent else {
self.rotate(p, c);
break;
};
if (self.obj_pool[g].children[0] == Some(p))
== (self.obj_pool[p].children[0] == Some(c))
{
self.rotate(g, p);
self.rotate(p, c);
} else {
self.rotate(p, c);
self.rotate(g, c);
}
}
}
fn insert(&mut self, value: T) {
let n = self.obj_pool.insert(Node::new(value));
if let Some(root) = self.root {
let mut p = root;
loop {
let dir = if self.obj_pool[n].value < self.obj_pool[p].value {
0
} else {
1
};
match self.obj_pool[p].children[dir] {
Some(c) => p = c,
None => {
self.link(p, Some(n), dir);
self.splay(n);
break;
}
}
}
} else {
self.root = Some(n);
}
}
fn print(&self, node: Option<ObjId>, indent: usize)
where
T: std::fmt::Display,
{
if let Some(node) = node {
self.print(self.obj_pool[node].children[0], indent + 3);
println!("{:width$}{}", "", self.obj_pool[node].value, width = indent);
self.print(self.obj_pool[node].children[1], indent + 3);
}
}
}
fn main() {
let mut splay = Splay::new();
let mut num = 1u32;
for _ in 0..30 {
num = num.wrapping_mul(17).wrapping_add(255);
splay.insert(num);
}
splay.print(splay.root, 0);
}