vec-arena/examples/splay-tree.rs

188 lines
4.9 KiB
Rust
Raw Normal View History

2016-11-14 19:41:37 +00:00
use vec_arena::Arena;
2016-10-22 23:35:26 +00:00
2016-10-28 11:07:52 +00:00
/// The null index, akin to null pointers.
2016-11-14 19:41:37 +00:00
///
/// Just like a null pointer indicates an address no object is ever stored at,
/// the null index indicates an index no object is ever stored at.
///
/// Number `!0` is the largest possible value representable by `usize`.
2016-10-28 11:07:52 +00:00
const NULL: usize = !0;
2016-10-22 23:35:26 +00:00
struct Node<T> {
2016-11-14 19:41:37 +00:00
/// Parent node.
2016-10-22 23:35:26 +00:00
parent: usize,
2016-11-14 19:41:37 +00:00
/// Left and right child.
2016-10-22 23:35:26 +00:00
children: [usize; 2],
2016-11-14 19:41:37 +00:00
/// Actual value stored in node.
2016-10-22 23:35:26 +00:00
value: T,
}
impl<T> Node<T> {
fn new(value: T) -> Node<T> {
Node {
2016-10-28 11:07:52 +00:00
parent: NULL,
children: [NULL, NULL],
2016-10-22 23:35:26 +00:00
value: value,
}
}
}
struct Splay<T> {
2016-11-14 19:41:37 +00:00
/// This is where nodes are stored.
arena: Arena<Node<T>>,
/// The root node.
2016-10-22 23:35:26 +00:00
root: usize,
}
impl<T: Ord> Splay<T> {
2016-10-28 00:31:37 +00:00
/// Constructs a new, empty splay tree.
2016-10-22 23:35:26 +00:00
fn new() -> Splay<T> {
Splay {
2016-12-20 17:49:45 +00:00
arena: Arena::new(),
2016-10-28 11:07:52 +00:00
root: NULL,
2016-10-22 23:35:26 +00:00
}
}
2016-10-28 00:31:37 +00:00
/// 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;
2016-10-28 11:07:52 +00:00
if c != NULL {
2016-10-28 00:31:37 +00:00
self.arena[c].parent = p;
}
}
2016-10-22 23:35:26 +00:00
2016-10-28 00:31:37 +00:00
/// 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
2016-10-22 23:35:26 +00:00
2016-10-28 00:31:37 +00:00
// 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);
2016-10-22 23:35:26 +00:00
2016-10-28 11:07:52 +00:00
if g == NULL {
2016-10-28 00:31:37 +00:00
// There is no grandparent, so `c` becomes the root.
self.root = c;
2016-10-28 11:07:52 +00:00
self.arena[c].parent = NULL;
2016-10-22 23:35:26 +00:00
} else {
2016-10-28 00:31:37 +00:00
// Link `g` and `c` together.
let dir = if self.arena[g].children[0] == p { 0 } else { 1 };
self.link(g, c, dir);
2016-10-22 23:35:26 +00:00
}
}
2016-11-14 19:41:37 +00:00
/// Splays a node, rebalancing the tree in process.
2016-10-28 00:31:37 +00:00
fn splay(&mut self, c: usize) {
2016-10-22 23:35:26 +00:00
loop {
2016-10-28 00:31:37 +00:00
// 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;
2016-10-28 11:07:52 +00:00
if p == NULL {
2016-10-28 00:31:37 +00:00
// There is no parent. That means `c` is the root.
2016-10-22 23:35:26 +00:00
break;
}
2016-10-28 00:31:37 +00:00
// Find the grandparent.
let g = self.arena[p].parent;
2016-10-28 11:07:52 +00:00
if g == NULL {
2016-11-14 19:41:37 +00:00
// There is no grandparent. Just one more rotation is left.
2016-10-28 00:31:37 +00:00
// Zig step.
self.rotate(p, c);
2016-10-22 23:35:26 +00:00
break;
}
2016-10-28 00:31:37 +00:00
if (self.arena[g].children[0] == p) == (self.arena[p].children[0] == c) {
// Zig-zig step.
self.rotate(g, p);
self.rotate(p, c);
2016-10-22 23:35:26 +00:00
} else {
2016-10-28 00:31:37 +00:00
// Zig-zag step.
self.rotate(p, c);
self.rotate(g, c);
2016-10-22 23:35:26 +00:00
}
}
}
2016-10-28 00:31:37 +00:00
/// Inserts a new node with specified `value`.
2016-10-22 23:35:26 +00:00
fn insert(&mut self, value: T) {
2016-10-28 00:31:37 +00:00
// 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));
2016-10-22 23:35:26 +00:00
2016-10-28 11:07:52 +00:00
if self.root == NULL {
2016-10-28 00:31:37 +00:00
self.root = n;
2016-10-22 23:35:26 +00:00
} else {
2016-10-28 00:31:37 +00:00
let mut p = self.root;
2016-10-22 23:35:26 +00:00
loop {
2016-10-28 00:31:37 +00:00
// Decide whether to go left or right.
let dir = if self.arena[n].value < self.arena[p].value {
0
} else {
1
};
2016-10-28 00:31:37 +00:00
let c = self.arena[p].children[dir];
2016-10-22 23:35:26 +00:00
2016-10-28 11:07:52 +00:00
if c == NULL {
2016-10-28 00:31:37 +00:00
self.link(p, n, dir);
self.splay(n);
2016-10-22 23:35:26 +00:00
break;
}
2016-10-28 00:31:37 +00:00
p = c;
2016-10-22 23:35:26 +00:00
}
}
}
2016-11-14 19:41:37 +00:00
/// Pretty-prints the subtree rooted at `node`, indented by `indent` spaces.
fn print(&self, node: usize, indent: usize)
where
T: std::fmt::Display,
{
2016-10-28 11:07:52 +00:00
if node != NULL {
2016-10-28 00:31:37 +00:00
// Print the left subtree.
2016-11-14 19:41:37 +00:00
self.print(self.arena[node].children[0], indent + 3);
2016-10-28 00:31:37 +00:00
// Print the current node.
2016-11-14 19:41:37 +00:00
println!("{:width$}{}", "", self.arena[node].value, width = indent);
2016-10-28 00:31:37 +00:00
// Print the right subtree.
2016-11-14 19:41:37 +00:00
self.print(self.arena[node].children[1], indent + 3);
2016-10-22 23:35:26 +00:00
}
}
}
fn main() {
let mut splay = Splay::new();
2016-10-28 00:31:37 +00:00
// Insert a bunch of pseudorandom numbers.
2016-10-22 23:35:26 +00:00
let mut num = 1u32;
2016-11-14 20:30:03 +00:00
for _ in 0..30 {
2016-10-22 23:35:26 +00:00
num = num.wrapping_mul(17).wrapping_add(255);
splay.insert(num);
}
2016-10-28 00:31:37 +00:00
// Display the whole splay tree.
splay.print(splay.root, 0);
2016-10-22 23:35:26 +00:00
}