I'm working with a Binary Tree defined as such:
(View in Playground)
type Tree = Rc<RefCell<TreeNode>>;
#[derive(Debug)]
pub struct TreeNode {
pub val: i32,
pub left: Option<Tree>,
pub right: Option<Tree>,
}
impl TreeNode {
#[inline]
pub fn new(val: i32) -> Self {
TreeNode {
val,
left: None,
right: None,
}
}
}
Id like to create an insert
function, and can do so using a stack just fine:
pub fn insert(root: &mut Option<Tree>, val: i32) {
let mut current_node = match root {
Some(node) => node.clone(),
None => {
*root = Some(Rc::new(RefCell::new(TreeNode::new(val))));
return;
}
};
//// USING STACK
let mut stack: Vec<Tree> = Vec::new();
stack.push(current_node.clone());
while let Some(node) = stack.pop() {
let mut node = node.borrow_mut();
if val < node.val {
match &node.left {
None => node.left = Some(Rc::new(RefCell::new(TreeNode::new(val)))),
Some(n) => stack.push(n.clone()),
}
} else {
match &node.right {
None => node.right = Some(Rc::new(RefCell::new(TreeNode::new(val)))),
Some(n) => stack.push(n.clone()),
}
}
}
}
But, shouldn't it be possible to traverse the nodes with a pointer/RC and avoid the stack? My first attempt runs in to the borrow checker. Is there something I'm missing here?
pub fn insert(root: &mut Option<Tree>, val: i32) {
let mut current_node = match root {
Some(node) => node.clone(),
None => {
*root = Some(Rc::new(RefCell::new(TreeNode::new(val))));
return;
}
};
////USING POINTER?
loop {
let node_value = current_node.borrow().val;
if val < node_value {
if current_node.borrow().left.is_none() {
current_node.borrow_mut().left = Some(Rc::new(RefCell::new(TreeNode::new(val))));
} else {
current_node = current_node.borrow().left.as_ref().unwrap().clone();
}
} else {
if current_node.borrow().right.is_none() {
current_node.borrow_mut().right = Some(Rc::new(RefCell::new(TreeNode::new(val))));
} else {
current_node = current_node.borrow().right.as_ref().unwrap().clone();
}
}
}
The borrow checker error:
error[E0506]: cannot assign to `current_node` because it is borrowed
--> src/merge_two_bin_trees.rs:54:17
|
54 | current_node = current_node.borrow().right.as_ref().unwrap().clone();
| ^^^^^^^^^^^^ --------------------- - ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, TreeNode>`
| | |
| | borrow of `current_node` occurs here
| | a temporary with access to the borrow is created here ...
| assignment to borrowed `current_node` occurs here
|
= note: borrow occurs due to deref coercion to `RefCell<TreeNode>`
I understand this borrow checker error, but is there a way to accomplish this?