AVL tree/Rust

From Rosetta Code
/// This implementation uses an addressable vector as the tree's store.
/// It is possible to construct a mutable tree using Rc<RefCell<>>,
/// but it adds some complexity.
///
/// "Pointers" to nodes are indices into the vector store, and have
/// trait Copy.
///
/// The index of a node in the vector store should not be confused with its key.
extern crate rand;
extern crate term_painter;
 
use std::cmp::Ordering;
use std::fmt::{Debug, Display, Formatter, Result};
 
use rand::distributions::Uniform;
use rand::Rng;
use term_painter::Color::*;
use term_painter::ToStyle;
 
pub type NodePtr = Option<usize>;
 
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Side {
Left,
Right,
Up,
Root,
}
 
#[derive(Debug, PartialEq, Clone, Copy)]
enum DisplayElement {
TrunkSpace,
SpaceLeft,
SpaceRight,
SpaceSpace,
Root,
}
 
impl DisplayElement {
fn string(&self) -> String {
match *self {
DisplayElement::TrunkSpace => " │ ".to_string(),
DisplayElement::SpaceRight => " ┌───".to_string(),
DisplayElement::SpaceLeft => " └───".to_string(),
DisplayElement::SpaceSpace => " ".to_string(),
DisplayElement::Root => "├──".to_string(),
}
}
}
 
/// Handedness of balanced insert and delete operations differs only by values encapsulated here.
struct BalanceConstants {
bal_incr: i8,
this_side: Side,
that_side: Side,
key_order: Ordering, // Ins only
// These are used in the +1/-1 & -1/+1 deletion cases
gcm1_child_adj: i8, // Del only, balance adjustment to child for b = -1 grandchild
gcm1_parent_adj: i8, // Del only, balance adjustment to parent for b = -1 grandchild
gcp1_child_adj: i8, // Del only, balance adjustment to child for b = 1 grandchild
gcp1_parent_adj: i8, // Del only, balance adjustment to parent for b = 1 grandchild
}
 
const BALANCE_CONSTANTS_A: BalanceConstants = BalanceConstants {
bal_incr: -1,
this_side: Side::Left,
that_side: Side::Right,
key_order: Ordering::Greater,
gcm1_child_adj: 0,
gcm1_parent_adj: 1,
gcp1_child_adj: -1,
gcp1_parent_adj: 0,
};
 
const BALANCE_CONSTANTS_B: BalanceConstants = BalanceConstants {
bal_incr: 1,
this_side: Side::Right,
that_side: Side::Left,
key_order: Ordering::Less,
gcm1_child_adj: 1,
gcm1_parent_adj: 0,
gcp1_child_adj: 0,
gcp1_parent_adj: -1,
};
 
#[derive(Debug, Clone, Copy)]
pub struct Node<K, V> {
key: K,
value: V,
balance: i8,
left: NodePtr,
right: NodePtr,
up: NodePtr,
}
 
#[derive(Debug)]
pub struct AVLTree<K, V> {
root: NodePtr,
store: Vec<Node<K, V>>,
}
 
impl<K: Ord + Copy + Debug + Display, V: Debug + Copy + Display> Default for AVLTree<K, V> {
fn default() -> Self {
AVLTree::new()
}
}
 
impl<K: Ord + Copy + Debug + Display, V: Debug + Copy + Display> AVLTree<K, V> {
pub fn get_node(&self, np: NodePtr) -> Node<K, V> {
assert!(np.is_some());
self.store[np.unwrap()]
}
 
pub fn get_balance(&self, np: NodePtr) -> i8 {
assert!(np.is_some());
self.store[np.unwrap()].balance
}
 
pub fn get_key(&self, np: NodePtr) -> K {
assert!(np.is_some());
self.store[np.unwrap()].key
}
 
pub fn get_value(&self, np: NodePtr) -> V {
assert!(np.is_some());
self.store[np.unwrap()].value
}
 
pub fn get_pointer(&self, np: NodePtr, side: Side) -> NodePtr {
assert!(np.is_some());
self.store[np.unwrap()].get_ptr(side)
}
 
pub fn set_balance(&mut self, np: NodePtr, bal: i8) {
assert!(np.is_some());
self.store[np.unwrap()].balance = bal;
}
 
pub fn set_key(&mut self, np: NodePtr, to: K) {
assert!(np.is_some());
self.store[np.unwrap()].key = to;
}
 
pub fn set_value(&mut self, np: NodePtr, to: V) {
assert!(np.is_some());
self.store[np.unwrap()].value = to;
}
 
pub fn set_pointer(&mut self, np: NodePtr, side: Side, to: NodePtr) {
assert!(np.is_some());
self.store[np.unwrap()].set_ptr(side, to);
}
 
pub fn increment_balance(&mut self, np: NodePtr, delta: i8) -> i8 {
assert!(np.is_some());
self.store[np.unwrap()].balance += delta;
self.store[np.unwrap()].balance
}
 
pub fn new() -> Self {
AVLTree {
root: None,
store: Vec::<Node<K, V>>::with_capacity(20_000),
}
}
 
/// Insert key-value
pub fn insert(&mut self, k: K, v: V) -> Option<Node<K, V>> {
let (n, _) = self.insert_node(Node::new(k, v));
n
}
 
/// Insert Node struct
pub fn insert_node(&mut self, mut n: Node<K, V>) -> (Option<Node<K, V>>, Side) {
if self.root.is_none() {
assert!(self.store.is_empty());
self.store.push(n);
self.root = Some(0);
return (Some(n), Side::Root);
}
 
let mut p = self.root; // Possibly None
let mut prev = p;
let mut side = Side::Left;
while p.is_some() {
prev = p;
match n.key.cmp(&self.get_key(p)) {
Ordering::Less => {
side = Side::Left;
p = self.get_pointer(p, side);
}
Ordering::Greater => {
side = Side::Right;
p = self.get_pointer(p, side);
}
Ordering::Equal => {
println!("Key exists");
return (None, side);
}
}
}
// Set child's pointer
n.up = prev;
// Stow the node
self.store.push(n);
// Set parent's pointer
let ptr = Some(self.store.len() - 1);
self.set_pointer(prev, side, ptr);
(Some(n), side)
}
 
/// Insert key-value and rebalance
pub fn insert_bal(&mut self, k: K, v: V) -> Option<Node<K, V>> {
self.insert_node_bal(Node::new(k, v))
}
 
/// Insert Node struct and rebalance
pub fn insert_node_bal(&mut self, n: Node<K, V>) -> Option<Node<K, V>> {
let (nins, side) = self.insert_node(n);
if nins.is_none() || side == Side::Root {
return nins;
}
 
let mut p = nins.unwrap().up;
let mut is_left = side == Side::Left;
 
while p.is_some() {
let i_c = get_insertion_constants(is_left);
 
let b = self.increment_balance(p, i_c.bal_incr);
if b == 0 {
break; // No further adjustments necessary
} else if b.abs() > 1 {
let child_p = self.get_pointer(p, i_c.this_side);
match self.get_balance(child_p) * b {
2 => {
// -2/-1 & +2/+1 patterns
self.single_rotation(i_c.this_side, p, child_p);
self.set_balance(p, 0);
self.set_balance(child_p, 0);
break;
}
-2 => {
// -2/+1 & +2/-1 patterns
let grand_p = self.get_pointer(child_p, i_c.that_side);
self.double_rotation(i_c.this_side, p, child_p, grand_p);
if self.get_pointer(child_p, i_c.this_side).is_none() {
// Degenerate case, no subtrees
self.set_balance(child_p, 0);
self.set_balance(p, 0);
} else if n.key.cmp(&self.get_key(grand_p)) == i_c.key_order {
self.set_balance(child_p, i_c.bal_incr);
self.set_balance(p, 0);
} else {
self.set_balance(child_p, 0);
self.set_balance(p, -i_c.bal_incr);
}
self.set_balance(grand_p, 0);
break;
}
_ => unreachable!(),
}
}
 
let child_p = p;
p = self.get_pointer(p, Side::Up);
if p.is_some() {
let left_p = self.get_pointer(p, Side::Left);
is_left = left_p.is_some() && left_p == child_p;
}
}
 
nins
}
 
/// Remove the node at index from the store and patch the hole in the vector,
/// modifying pointers in the moved node's parents and children.
fn remove_carefully(&mut self, p: NodePtr) {
assert!(p.is_some());
let index = p.unwrap();
let old_index = self.store.len() - 1;
self.store.swap_remove(index);
 
if index == old_index {
// Nothing moved
return;
}
 
// Element -1 has moved into the spot _index_. The in-pointers that need modifying
// belong to that element's parent and children.
 
// Fix child pointer in parent:
let parent_p = self.get_pointer(p, Side::Up);
if parent_p.is_some() {
let l = self.get_pointer(parent_p, Side::Left);
if l == Some(old_index) {
self.set_pointer(parent_p, Side::Left, Some(index));
} else {
self.set_pointer(parent_p, Side::Right, Some(index));
}
}
 
// Fix parent pointers in children:
let l = self.get_pointer(p, Side::Left);
let r = self.get_pointer(p, Side::Right);
if l.is_some() {
self.set_pointer(l, Side::Up, Some(index));
}
if r.is_some() {
self.set_pointer(r, Side::Up, Some(index));
}
 
// Fix root if necessary
if self.root == Some(old_index) {
self.root = Some(index);
}
}
 
/// Uses delete-by-copy procedure if node with key k has two children.
/// Returns (parent, side) tuple.
pub fn delete(&mut self, k: K) -> (NodePtr, Side) {
let mut p = self.root;
let mut prev = None;
let mut res = None;
let mut side = Side::Root;
while p.is_some() {
match k.cmp(&self.get_key(p)) {
Ordering::Equal => {
break;
}
Ordering::Less => {
prev = p;
side = Side::Left;
p = self.get_pointer(p, side);
}
Ordering::Greater => {
prev = p;
side = Side::Right;
p = self.get_pointer(p, side);
}
}
}
 
if p.is_none() {
println!("Key {:?} not found", k);
return (res, side);
}
 
let n = self.get_node(p);
// Is this a leaf?
if n.is_leaf() {
if n.key.cmp(&self.get_key(self.root)) == Ordering::Equal {
self.root = None;
assert_eq!(self.store.len(), 1);
} else {
self.set_pointer(prev, side, None);
}
self.remove_carefully(p);
// The prev pointer is now stale
res = if prev == Some(self.store.len()) {
p
} else {
prev
};
 
// Is this a one-child node?
} else if n.left.is_none() || n.right.is_none() {
let ch = if n.left.is_some() { n.left } else { n.right };
if n.key.cmp(&self.get_key(self.root)) == Ordering::Equal {
self.set_pointer(ch, Side::Up, None);
self.root = ch;
} else {
self.set_pointer(prev, side, ch);
self.set_pointer(ch, Side::Up, prev);
}
self.remove_carefully(p);
// The prev pointer is now stale
res = if prev == Some(self.store.len()) {
p
} else {
prev
};
 
// Complicated case: two children, do delete-by-copy. Replace n with its first
// predecessor (the mirror image using the first successor would work as well).
} else {
let mut tmp = n.left;
let mut last = tmp;
prev = self.get_pointer(tmp, Side::Up);
while tmp.is_some() && self.get_pointer(last, Side::Right).is_some() {
prev = self.get_pointer(tmp, Side::Up);
last = tmp;
tmp = self.get_pointer(tmp, Side::Right);
}
tmp = last;
// Copy ...
let the_key = self.get_key(tmp);
let the_value = self.get_value(tmp);
self.set_key(p, the_key);
self.set_value(p, the_value);
 
let left_ptr = self.get_pointer(tmp, Side::Left);
if prev == p {
self.set_pointer(p, Side::Left, left_ptr);
if left_ptr.is_some() {
self.set_pointer(left_ptr, Side::Up, p);
}
side = Side::Left;
} else {
self.set_pointer(prev, Side::Right, left_ptr);
if left_ptr.is_some() {
self.set_pointer(left_ptr, Side::Up, prev);
}
side = Side::Right;
}
 
self.remove_carefully(tmp);
// The prev pointer is now stale
res = if prev.unwrap() == self.store.len() {
tmp
} else {
prev
};
}
 
(res, side)
}
 
/// Rebalance on delete
pub fn delete_bal(&mut self, k: K) -> Option<Node<K, V>> {
// slug: (pointer to parent of deleted node, side of deleted node)
let slug = self.delete(k);
let (pdel, side) = slug;
if pdel.is_none() {
return None;
};
let ndel = self.get_node(pdel);
 
let mut p = pdel;
let mut is_left = side == Side::Left;
 
// Rebalance and update balance factors. There are two different rotation sequences that
// are the same within handedness,
// and the +1/-1 / -1/+1 sequence has three possible balance adjustments
// depending on the grandchild.
while p.is_some() {
let d_c = get_deletion_constants(is_left);
 
let b = self.increment_balance(p, d_c.bal_incr);
if b.abs() == 1 {
break; // No further adjustments necessary
} else if b.abs() > 1 {
let child_p = self.get_pointer(p, d_c.this_side);
match self.get_balance(child_p) * b {
2 => {
// +1/+1 & -1/-1 patterns
self.single_rotation(d_c.this_side, p, child_p);
self.set_balance(p, 0);
p = self.get_pointer(p, Side::Up);
self.set_balance(p, 0);
}
0 => {
// +1/0 & -1/0 patterns
self.single_rotation(d_c.this_side, p, child_p);
self.set_balance(p, d_c.bal_incr);
p = self.get_pointer(p, Side::Up);
self.set_balance(p, -d_c.bal_incr);
break; // No height change
}
-2 => {
// +1/-1/x & -1/+1/x patterns
let grand_p = self.get_pointer(child_p, d_c.that_side);
self.double_rotation(d_c.this_side, p, child_p, grand_p);
// p is now one child, grand_p is the other, child_p is their parent
match self.get_balance(grand_p) {
-1 => {
self.set_balance(p, d_c.gcm1_parent_adj);
self.set_balance(child_p, d_c.gcm1_child_adj);
}
0 => {
self.set_balance(p, 0);
self.set_balance(child_p, 0);
}
1 => {
self.set_balance(p, d_c.gcp1_parent_adj);
self.set_balance(child_p, d_c.gcp1_child_adj);
}
_ => unreachable!(),
}
self.set_balance(grand_p, 0);
p = self.get_pointer(p, Side::Up);
}
_ => unreachable!(),
}
}
 
let child_p = p;
p = self.get_pointer(p, Side::Up);
if p.is_some() {
let left_p = self.get_pointer(p, Side::Left);
is_left = left_p.is_some() && left_p == child_p;
}
}
 
Some(ndel)
}
 
/// Returns node value
pub fn lookup(&self, k: K) -> Option<V> {
self.search(k).map(|n| n.value)
}
 
/// Returns node (not pointer)
pub fn search(&self, k: K) -> Option<Node<K, V>> {
let mut p = self.root;
let mut res = None;
 
while p.is_some() {
match k.cmp(&self.get_key(p)) {
Ordering::Less => {
p = self.get_pointer(p, Side::Left);
}
Ordering::Greater => {
p = self.get_pointer(p, Side::Right);
}
Ordering::Equal => {
res = Some(self.get_node(p));
break;
}
}
}
res
}
 
/// Do an in-order traversal, where a "visit" prints the row with that node in it.
fn display(&self, p: NodePtr, side: Side, e: &[DisplayElement], f: &mut Formatter) {
if p.is_none() {
return;
}
 
let mut elems = e.to_vec();
let node = self.get_node(p);
let mut tail = DisplayElement::SpaceSpace;
if node.up != self.root {
// Direction switching, need trunk element to be printed for lines before that node
// is visited.
let new_elem = if side == Side::Left && node.right.is_some() {
DisplayElement::TrunkSpace
} else {
DisplayElement::SpaceSpace
};
elems.push(new_elem);
}
let hindex = elems.len() - 1;
self.display(node.right, Side::Right, &elems, f);
 
if p == self.root {
elems[hindex] = DisplayElement::Root;
tail = DisplayElement::TrunkSpace;
} else if side == Side::Right {
// Right subtree finished
elems[hindex] = DisplayElement::SpaceRight;
// Prepare trunk element in case there is a left subtree
tail = DisplayElement::TrunkSpace;
} else
// if side == Side::Left
{
elems[hindex] = DisplayElement::SpaceLeft;
let parent_p = self.get_pointer(p, Side::Up);
let gp_p = self.get_pointer(parent_p, Side::Up);
if gp_p.is_some() && self.get_pointer(gp_p, Side::Right) == parent_p {
// Direction switched, need trunk element starting with this node/line
elems[hindex - 1] = DisplayElement::TrunkSpace;
}
}
 
// Visit node => print accumulated elements. Each node gets a line.
{
for e in elems.clone() {
let _ = write!(f, "{}", e.string());
}
let _ = write!(
f,
"{key:>width$} ",
key = Green.bold().paint(node.key),
width = 2
);
let _ = write!(
f,
"{value:>width$} ",
value = Blue.bold().paint(format!("{:.*}", 2, node.value)),
width = 4
);
let _ = write!(
f,
"{bal:<-width$}\n",
bal = Red.bold().paint(node.balance),
width = 2
);
 
elems[hindex] = tail;
}
 
self.display(node.left, Side::Left, &elems, f);
}
 
pub fn gather_balances(&self) -> (Vec<K>, Vec<i8>) {
let mut keys = Vec::<K>::new();
let mut bals = Vec::<i8>::new();
 
self.gather_balances_impl(self.root, &mut keys, &mut bals);
(keys, bals)
}
 
fn gather_balances_impl(&self, p: NodePtr, k: &mut Vec<K>, b: &mut Vec<i8>) {
if p.is_none() {
return;
}
let r = self.get_pointer(p, Side::Right);
self.gather_balances_impl(r, k, b);
k.push(self.get_key(p));
b.push(self.get_balance(p));
let l = self.get_pointer(p, Side::Left);
self.gather_balances_impl(l, k, b)
}
 
pub fn compute_balances(&mut self, p: NodePtr) -> i8 {
self.compute_balances_impl(p, 0)
}
 
fn compute_balances_impl(&mut self, p: NodePtr, level: i8) -> i8 {
if p.is_none() {
return level - 1;
}
let r = self.get_pointer(p, Side::Right);
let l = self.get_pointer(p, Side::Left);
let rb = self.compute_balances_impl(r, level + 1);
let lb = self.compute_balances_impl(l, level + 1);
self.set_balance(p, rb - lb);
std::cmp::max(rb, lb)
}
 
/// P Q
/// / \ => / \
/// h Q P h'
fn rotate_left(&mut self, p: NodePtr, q: NodePtr) {
assert!(p.is_some());
assert!(q.is_some());
let p_parent = self.get_pointer(p, Side::Up);
// Take care of parent pointers
self.set_pointer(q, Side::Up, p_parent);
self.set_pointer(p, Side::Up, q);
let ql = self.get_pointer(q, Side::Left);
if ql.is_some() {
self.set_pointer(ql, Side::Up, p);
}
 
// Take care of child pointers
self.set_pointer(q, Side::Left, p);
self.set_pointer(p, Side::Right, ql);
if p_parent.is_some() {
let side = if self.get_pointer(p_parent, Side::Right) == p {
Side::Right
} else {
Side::Left
};
self.set_pointer(p_parent, side, q);
} else {
self.root = q;
}
}
 
/// P Q
/// / \ => / \
/// Q h h' P
fn rotate_right(&mut self, p: NodePtr, q: NodePtr) {
assert!(p.is_some());
assert!(q.is_some());
let p_parent = self.get_pointer(p, Side::Up);
// Take care of parent pointers
self.set_pointer(q, Side::Up, p_parent);
self.set_pointer(p, Side::Up, q);
let qr = self.get_pointer(q, Side::Right);
if qr.is_some() {
self.set_pointer(qr, Side::Up, p);
}
 
// Take care of child pointers
self.set_pointer(q, Side::Right, p);
self.set_pointer(p, Side::Left, qr);
if p_parent.is_some() {
let side = if self.get_pointer(p_parent, Side::Right) == p {
Side::Right
} else {
Side::Left
};
self.set_pointer(p_parent, side, q);
} else {
self.root = q;
}
}
 
fn single_rotation(&mut self, side: Side, p: NodePtr, q: NodePtr) {
if side == Side::Left {
self.rotate_right(p, q);
} else {
self.rotate_left(p, q);
}
}
 
fn double_rotation(&mut self, side: Side, p: NodePtr, child_p: NodePtr, grand_p: NodePtr) {
if side == Side::Left {
self.rotate_left(child_p, grand_p);
self.rotate_right(p, grand_p);
} else {
self.rotate_right(child_p, grand_p);
self.rotate_left(p, grand_p);
}
}
}
 
impl<K: Ord + Copy, V: Copy> Node<K, V> {
pub fn new(k: K, v: V) -> Node<K, V> {
Node {
key: k,
value: v,
balance: 0,
left: None,
right: None,
up: None,
}
}
 
pub fn is_leaf(&self) -> bool {
self.left.is_none() && self.right.is_none()
}
 
pub fn set_ptr(&mut self, side: Side, to: NodePtr) {
let field = match side {
Side::Up => &mut self.up,
Side::Left => &mut self.left,
_ => &mut self.right,
};
*field = to;
}
 
pub fn get_ptr(&self, side: Side) -> NodePtr {
match side {
Side::Up => self.up,
Side::Left => self.left,
_ => self.right,
}
}
}
 
impl<K: Ord + Copy + Debug + Display, V: Debug + Copy + Display> Display for AVLTree<K, V> {
fn fmt(&self, f: &mut Formatter) -> Result {
if self.root.is_none() {
write!(f, "[empty]")
} else {
let v: Vec<DisplayElement> = Vec::new();
self.display(self.root, Side::Up, &v, f);
Ok(())
}
}
}
 
fn get_insertion_constants(is_left: bool) -> &'static BalanceConstants {
if is_left {
&BALANCE_CONSTANTS_A
} else {
&BALANCE_CONSTANTS_B
}
}
 
fn get_deletion_constants(is_left: bool) -> &'static BalanceConstants {
get_insertion_constants(!is_left)
}
 
pub fn random_bal_tree(n: u32) -> AVLTree<i32, f32> {
let mut tree: AVLTree<i32, f32> = AVLTree::new();
let mut rng = rand::thread_rng();
// `Uniform` rather than `gen_range`'s `Uniform::sample_single` for speed
let key_range = Uniform::new(-(n as i32) / 2, (n as i32) / 2);
let value_range = Uniform::new(-1.0, 1.0);
tree.insert_bal(0, rng.sample(value_range));
for _ in 0..n {
tree.insert_bal(rng.sample(key_range), rng.sample(value_range));
}
tree
}
 
#[cfg(test)]
mod tests {
use rand::{seq, thread_rng};
 
use super::AVLTree;
use random_bal_tree;
 
#[test]
fn test_insert() {
let mut tree: AVLTree<i32, f32> = AVLTree::new();
tree.insert(0, 0.0);
tree.insert(8, 8.8);
tree.insert(-8, -8.8);
assert!(tree.insert(4, 4.4).is_some());
tree.insert(12, 12.12);
 
assert_eq!(tree.lookup(4), Some(4.4));
assert_eq!(tree.lookup(5), None);
assert_eq!(tree.lookup(-8), Some(-8.8));
 
let s = &tree.store;
assert_eq!(
s[s[s[tree.root.unwrap()].right.unwrap()].right.unwrap()].value,
12.12
);
assert_eq!(
s[s[s[tree.root.unwrap()].right.unwrap()].right.unwrap()].left,
None
);
}
 
#[test]
fn test_delete() {
let mut tree: AVLTree<i32, f32> = AVLTree::new();
tree.insert(0, 0.0);
tree.insert(8, 8.8);
tree.insert(-8, -8.8);
assert!(tree.insert(4, 4.4).is_some());
tree.insert(12, 12.12);
 
// delete leaf
tree.delete(12);
assert_eq!(tree.lookup(12), None);
let mut n = tree.search(8).unwrap();
assert_eq!(n.right, None);
 
// delete one-child node
tree.delete(4);
assert_eq!(tree.lookup(4), None);
n = tree.search(0).unwrap();
assert_eq!(tree.store[n.right.unwrap()].key, 8);
 
// delete two-child node
tree.insert(6, 6.6);
tree.insert(10, 10.10);
tree.insert(7, 7.7);
tree.delete(8);
n = tree.search(7).unwrap();
assert_eq!(tree.store[n.left.unwrap()].key, 6);
assert_eq!(tree.store[n.right.unwrap()].key, 10);
assert_eq!(tree.store[n.up.unwrap()].key, 0);
 
// delete two-child root
tree.delete(0);
assert_eq!(tree.store[tree.root.unwrap()].key, -8);
 
// delete one-child root
tree.delete(-8);
assert_eq!(tree.store[tree.root.unwrap()].key, 7);
 
// delete no-child root
tree.delete(6);
tree.delete(7);
tree.delete(10);
assert!(tree.root.is_none());
assert_eq!(tree.store.len(), 0);
}
 
#[test]
fn test_rotate_left() {
let mut tree: AVLTree<i32, f32> = AVLTree::new();
tree.insert(0, 0.0);
tree.insert(8, 8.8);
tree.insert(4, 4.4);
tree.insert(-8, -8.8);
 
let mut r = tree.root;
let mut right = tree.store[r.unwrap()].right;
tree.rotate_left(r, right);
r = tree.root;
right = tree.store[r.unwrap()].right;
let left = tree.store[r.unwrap()].left;
let left_left = tree.store[left.unwrap()].left;
let left_right = tree.store[left.unwrap()].right;
assert_eq!(right, None);
assert_eq!(tree.store[left.unwrap()].key, 0);
assert_eq!(tree.store[left_left.unwrap()].key, -8);
assert_eq!(tree.store[left_right.unwrap()].key, 4);
assert_eq!(tree.store[r.unwrap()].key, 8);
}
 
#[test]
fn test_rotate_right() {
let mut tree: AVLTree<i32, f32> = AVLTree::new();
tree.insert(0, 0.0);
tree.insert(8, 8.8);
tree.insert(-8, -8.8);
tree.insert(-4, 4.4);
 
let mut r = tree.root;
let mut left = tree.store[r.unwrap()].left;
tree.rotate_right(r, left);
r = tree.root;
left = tree.store[r.unwrap()].left;
let right = tree.store[r.unwrap()].right;
let right_right = tree.store[right.unwrap()].right;
let right_left = tree.store[right.unwrap()].left;
assert_eq!(left, None);
assert_eq!(tree.store[right.unwrap()].key, 0);
assert_eq!(tree.store[right_right.unwrap()].key, 8);
assert_eq!(tree.store[right_left.unwrap()].key, -4);
assert_eq!(tree.store[r.unwrap()].key, -8);
}
 
#[test]
// This tree tests all four insertion types
fn test_balanced_inserts() {
let mut tree: AVLTree<i32, f32> = AVLTree::new();
tree.insert_bal(0, 0.0);
tree.insert_bal(8, 8.8);
tree.insert_bal(-8, -8.8);
tree.insert_bal(12, 12.12);
tree.insert_bal(16, 16.16);
tree.insert_bal(11, 11.11);
tree.insert_bal(4, 4.4);
tree.insert_bal(-10, -8.8);
tree.insert_bal(-12, -8.8);
tree.insert_bal(-9, -8.8);
 
let mut res = tree.gather_balances();
let (_, bals) = res;
assert!(bals.iter().max().unwrap() < &2);
assert!(bals.iter().min().unwrap() > &-2);
 
for _ in 0..10 {
tree = random_bal_tree(1000);
res = tree.gather_balances();
let (_, bals) = res;
assert!(bals.iter().max().unwrap() < &2);
assert!(bals.iter().min().unwrap() > &-2);
}
}
 
#[test]
/// This sequence hits all five rotation possibilities on each side.
fn test_balanced_deletes() {
let mut tree: AVLTree<i32, f32> = AVLTree::new();
tree.insert_bal(0, 0.0);
tree.insert_bal(-32, 0.0);
tree.insert_bal(32, 0.0);
tree.insert_bal(-64, 0.0);
tree.insert_bal(64, 0.0);
tree.delete_bal(64);
tree.delete_bal(32);
tree.delete_bal(-32);
tree.delete_bal(-64);
tree.delete_bal(0);
assert_eq!(tree.root, None);
assert_eq!(tree.store.len(), 0);
 
tree.insert_bal(0, 0.0);
tree.insert_bal(-32, 0.0);
tree.insert_bal(32, 0.0);
tree.insert_bal(-64, 0.0);
tree.insert_bal(64, 0.0);
tree.insert_bal(-16, 0.0);
tree.insert_bal(16, 0.0);
tree.insert_bal(-8, 0.0);
tree.insert_bal(8, 0.0);
tree.insert_bal(-12, 0.0);
tree.insert_bal(-7, 0.0);
tree.insert_bal(-6, 0.0);
tree.insert_bal(-11, 0.0);
 
tree.delete_bal(-64);
tree.delete_bal(-32);
tree.delete_bal(-7);
tree.delete_bal(-6);
tree.delete_bal(-16);
tree.delete_bal(-11);
tree.delete_bal(-12);
tree.delete_bal(8);
tree.delete_bal(-8);
tree.delete_bal(0);
tree.insert_bal(24, 0.0);
tree.insert_bal(8, 0.0);
tree.insert_bal(4, 0.0);
tree.insert_bal(128, 0.0);
tree.insert_bal(48, 0.0);
tree.delete_bal(32);
tree.delete_bal(48);
 
tree.insert_bal(-24, 0.0);
tree.insert_bal(-8, 0.0);
tree.insert_bal(-128, 0.0);
tree.insert_bal(-48, 0.0);
tree.insert_bal(-20, 0.0);
tree.insert_bal(-30, 0.0);
tree.insert_bal(-22, 0.0);
tree.insert_bal(-21, 0.0);
tree.delete_bal(24);
tree.delete_bal(64);
tree.delete_bal(-30);
tree.delete_bal(-22);
tree.delete_bal(-21);
tree.delete_bal(-128);
tree.delete_bal(128);
tree.delete_bal(-8);
tree.insert_bal(-96, 0.0);
tree.insert_bal(-95, 0.0);
tree.insert_bal(-10, 0.0);
tree.insert_bal(6, 0.0);
tree.delete_bal(-24);
 
let mut res = tree.gather_balances();
let (_, bals) = res;
assert!(bals.iter().max().unwrap() < &2);
assert!(bals.iter().min().unwrap() > &-2);
 
let mut p = tree.root;
while p.is_some() {
let key = tree.store[p.unwrap()].key;
tree.delete_bal(key);
p = tree.root;
}
assert_eq!(tree.root, None);
assert_eq!(tree.store.len(), 0);
 
// */*/+1 patterns
tree.insert(6, 0.0);
tree.insert(-1, 0.0);
tree.insert(9, 0.0);
tree.insert(7, 0.0);
tree.insert(3, 0.0);
tree.insert(-9, 0.0);
tree.insert(4, 0.0);
p = tree.root;
tree.compute_balances(p);
tree.delete_bal(-9);
res = tree.gather_balances();
let (_, bals) = res;
tree.compute_balances(p);
res = tree.gather_balances();
let (_, bals_after) = res;
assert_eq!(bals, bals_after);
 
tree.insert(6, 0.0);
tree.insert(-1, 0.0);
tree.insert(3, 0.0);
tree.insert(9, 0.0);
tree.insert(7, 0.0);
tree.insert(11, 0.0);
tree.insert(8, 0.0);
p = tree.root;
tree.compute_balances(p);
tree.delete_bal(-1);
res = tree.gather_balances();
let (_, bals) = res;
tree.compute_balances(p);
res = tree.gather_balances();
let (_, bals_after) = res;
assert_eq!(bals, bals_after);
 
let mut rng = thread_rng();
for _ in 0..100 {
tree = random_bal_tree(100);
let sample = seq::sample_iter(&mut rng, -50..50, 80).unwrap();
for i in sample {
tree.delete_bal(i);
}
}
 
res = tree.gather_balances();
let (_, bals) = res;
 
if bals.len() > 0 {
assert!(*bals.iter().max().unwrap() < 2);
assert!(*bals.iter().min().unwrap() > -2);
}
 
return;
}
}