I am implementing a binary search tree. The complete code is on the playground.
type Link<K, V> = Option<Box<Node<K, V>>>;
struct Node<K, V> {
key: K,
val: V,
left: Link<K, V>,
right: Link<K, V>,
n: usize, // nodes in subtree rooted here
}
pub struct BST<K, V> {
root: Link<K, V>, // root of BST
}
In the _delete()
helper method, I found it is necessary to add as_ref
when matching in the Equal
arm:
fn _delete(x: &mut Link<K, V>, k: &K) {
if let Some(node) = x {
match k.cmp(&node.key) {
Ordering::Less => { Self::_delete(&mut node.left, k);
node.n = Self::_size(&node.left) + Self::_size(&node.right) + 1;
},
Ordering::Greater => { Self::_delete(&mut node.right, k);
node.n = Self::_size(&node.left) + Self::_size(&node.right) + 1;
},
Ordering::Equal => {
match (node.left.as_ref(), node.right.as_ref()) {
(None, None) => *x = None,
(Some(_), None) => *x = node.left.take(),
(None, Some(_)) => *x = node.right.take(),
(Some(_), Some(_)) => {
*x = Self::extract_min(&mut node.right);
},
}
}
}
}
}
If I replace the Equal
arm with following code, it is correct in the syntax sense (although it is wrong logically)
Ordering::Equal => {
match node.left {
Some(_) => {},
_ => {},
}
}
I think it must be a borrow-checking problem, but I cannot figure out the difference between a plain variable (i.e., node.left
) and a tuple (i.e., (node.left, node.right)
) while matching. Why and when to use as_ref
while matching?