From 89b77b634c35293ba30f7449fd059dc1d4d9f3eb Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Fri, 28 Oct 2016 02:31:37 +0200 Subject: [PATCH] More comments --- examples/splay_tree.rs | 133 +++++++++++++++++++++++++++-------------- 1 file changed, 87 insertions(+), 46 deletions(-) diff --git a/examples/splay_tree.rs b/examples/splay_tree.rs index e73f1ce..fdee7dd 100644 --- a/examples/splay_tree.rs +++ b/examples/splay_tree.rs @@ -23,7 +23,8 @@ struct Splay { root: usize, } -impl Splay where T: Ord + Eq + Clone { +impl Splay where T: Ord { + /// Constructs a new, empty splay tree. fn new() -> Splay { Splay { arena: VecArena::new(), @@ -31,83 +32,120 @@ impl Splay where T: Ord + Eq + Clone { } } - // #[inline(always)] - fn rotate(&mut self, a: usize, b: usize) { - let p = self.arena[a].parent; - - let dir = if self.arena[a].children[0] == b { 0 } else { 1 }; - let t = self.arena[b].children[dir ^ 1]; - - self.arena[a].children[dir] = t; - if t != !0 { - self.arena[t].parent = a; + /// Links nodes `p` and `c` as parent and child with the specified direction. + #[inline(always)] + fn link(&mut self, p: usize, c: usize, dir: usize) { + self.arena[p].children[dir] = c; + if c != !0 { + self.arena[c].parent = p; } - self.arena[b].children[dir ^ 1] = a; - self.arena[a].parent = b; + } - if p == !0 { - self.root = b; - self.arena[b].parent = !0; + /// Performs a rotation on node `c`, whose parent is node `p`. + #[inline(always)] + fn rotate(&mut self, p: usize, c: usize) { + // Variables: + // - `c` is the child node + // - `p` is it's parent + // - `g` is it's grandparent + + // Find the grandparent. + let g = self.arena[p].parent; + + // The direction of p-c relationship. + let dir = if self.arena[p].children[0] == c { 0 } else { 1 }; + + // This is the child of `c` that needs to be reassigned to `p`. + let t = self.arena[c].children[dir ^ 1]; + + self.link(p, t, dir); + self.link(c, p, dir ^ 1); + + if g == !0 { + // There is no grandparent, so `c` becomes the root. + self.root = c; + self.arena[c].parent = !0; } else { - let dir = if self.arena[p].children[0] == a { 0 } else { 1 }; - self.arena[p].children[dir] = b; - self.arena[b].parent = p; + // Link `g` and `c` together. + let dir = if self.arena[g].children[0] == p { 0 } else { 1 }; + self.link(g, c, dir); } } - fn splay(&mut self, a: usize) { + /// Splays node + fn splay(&mut self, c: usize) { loop { - let b = self.arena[a].parent; - if b == !0 { + // Variables: + // - `c` is the current node + // - `p` is it's parent + // - `g` is it's grandparent + + // Find the parent. + let p = self.arena[c].parent; + if p == !0 { + // There is no parent. That means `c` is the root. break; } - let c = self.arena[b].parent; - if c == !0 { - self.rotate(b, a); + // Find the grandparent. + let g = self.arena[p].parent; + if g == !0 { + // There is no grandparent. Just one rotation is left. + // Zig step. + self.rotate(p, c); break; } - let is_l = self.arena[c].children[0] == b && self.arena[b].children[0] == a; - let is_r = self.arena[c].children[1] == b && self.arena[b].children[1] == a; - - if is_l || is_r { - self.rotate(c, b); - self.rotate(b, a); + if (self.arena[g].children[0] == p) == (self.arena[p].children[0] == c) { + // Zig-zig step. + self.rotate(g, p); + self.rotate(p, c); } else { - self.rotate(b, a); - self.rotate(c, a); + // Zig-zag step. + self.rotate(p, c); + self.rotate(g, c); } } } + /// Inserts a new node with specified `value`. fn insert(&mut self, value: T) { - let node = self.arena.insert(Node::new(value)); + // Variables: + // - `n` is the new node + // - `p` will be it's parent + // - `c` is the present child of `p` + + let n = self.arena.insert(Node::new(value)); if self.root == !0 { - self.root = node; + self.root = n; } else { - let mut curr = self.root; + let mut p = self.root; loop { - let dir = if self.arena[node].value < self.arena[curr].value { 0 } else { 1 }; - let next = self.arena[curr].children[dir]; + // Decide whether to go left or right. + let dir = if self.arena[n].value < self.arena[p].value { 0 } else { 1 }; + let c = self.arena[p].children[dir]; - if next == !0 { - self.arena[curr].children[dir] = node; - self.arena[node].parent = curr; - self.splay(node); + if c == !0 { + self.link(p, n, dir); + self.splay(n); break; - } else { - curr = next; } + p = c; } } } + /// Pretty-prints the subtree rooted at `node`, indented by `depth` spaces. fn print(&self, node: usize, depth: usize) where T: std::fmt::Display { if node != !0 { + // Print the left subtree. self.print(self.arena[node].children[0], depth + 1); + + // Print the current node. println!("{:width$}{}", "", self.arena[node].value, width = depth * 3); + + // Print the right subtree. self.print(self.arena[node].children[1], depth + 1); } } @@ -116,10 +154,13 @@ impl Splay where T: Ord + Eq + Clone { fn main() { let mut splay = Splay::new(); + // Insert a bunch of pseudorandom numbers. let mut num = 1u32; - for _ in 0..1000000 { + for _ in 0..30 { num = num.wrapping_mul(17).wrapping_add(255); splay.insert(num); } - // splay.print(splay.root, 0); + + // Display the whole splay tree. + splay.print(splay.root, 0); }