extern crate obj_pool; use obj_pool::{ObjPool, ObjId}; struct Node { /// Parent node. parent: Option, /// Left and right child. children: [Option; 2], /// Actual value stored in node. value: T, } impl Node { fn new(value: T) -> Node { Node { parent: None, children: [None, None], value, } } } struct Splay { /// This is where nodes are stored. obj_pool: ObjPool>, /// The root node. root: Option, } impl Splay where T: Ord { /// Constructs a new, empty splay tree. fn new() -> Splay { let obj_pool = ObjPool::new(); Splay { obj_pool, root: None, } } /// Links nodes `p` and `c` as parent and child with the specified direction. #[inline(always)] fn link(&mut self, p: ObjId, c: Option, dir: usize) { self.obj_pool[p].children[dir] = c; if let Some(c) = c { self.obj_pool[c].parent = p; } } /// Performs a rotation on node `c`, whose parent is node `p`. #[inline(always)] fn rotate(&mut self, p: ObjId, c: ObjId) { // Variables: // - `c` is the child node // - `p` is it's parent // - `g` is it's grandparent // Find the grandparent. let g = self.obj_pool[p].parent; // The direction of p-c relationship. let dir = if self.obj_pool[p].children[0] == c { 0 } else { 1 }; // This is the child of `c` that needs to be reassigned to `p`. let t = self.obj_pool[c].children[dir ^ 1]; self.link(p, t, dir); self.link(c, p, dir ^ 1); if let Some(g) = g { // Link `g` and `c` together. let dir = if self.obj_pool[g].children[0] == p { 0 } else { 1 }; self.link(g, c, dir); } else { // There is no grandparent, so `c` becomes the root. self.root = c; self.obj_pool[c].parent = None; } } /// Splays a node, rebalancing the tree in process. fn splay(&mut self, c: ObjId) { loop { // Variables: // - `c` is the current node // - `p` is it's parent // - `g` is it's grandparent // Find the parent. let p = self.obj_pool[c].parent; if p.is_none() { // There is no parent. That means `c` is the root. break; } // Find the grandparent. let g = self.obj_pool[p].parent; if g.is_none() { // There is no grandparent. Just one more rotation is left. // Zig step. self.rotate(p, c); break; } if (self.obj_pool[g].children[0] == p) == (self.obj_pool[p].children[0] == c) { // Zig-zig step. self.rotate(g, p); self.rotate(p, c); } else { // Zig-zag step. self.rotate(p, c); self.rotate(g, c); } } } /// Inserts a new node with specified `value`. fn insert(&mut self, value: T) { // Variables: // - `n` is the new node // - `p` will be it's parent // - `c` is the present child of `p` let n = self.obj_pool.insert(Node::new(value)); if let Some(root) = self.root { let mut p = root; loop { // Decide whether to go left or right. let dir = if self.obj_pool[n].value < self.obj_pool[p].value { 0 } else { 1 }; let c = self.obj_pool[p].children[dir]; if c.is_none() { self.link(p, n, dir); self.splay(n); break; } p = c; } } else { self.root = n; } } /// Pretty-prints the subtree rooted at `node`, indented by `indent` spaces. fn print(&self, node: ObjId, indent: usize) where T: std::fmt::Display { if node != self.null { // Print the left subtree. self.print(self.obj_pool[node].children[0], indent + 3); // Print the current node. println!("{:width$}{}", "", self.obj_pool[node].value, width = indent); // Print the right subtree. self.print(self.obj_pool[node].children[1], indent + 3); } } } fn main() { let mut splay = Splay::new(); // Insert a bunch of pseudorandom numbers. let mut num = 1u32; for _ in 0..30 { num = num.wrapping_mul(17).wrapping_add(255); splay.insert(num); } // Display the whole splay tree. splay.print(splay.root, 0); }