Can't do breadth-first search on a binary tree in Rust - rust

I've implemented a binary tree in Rust as a learning project but failed to transverse it to print the tree in a breadth-first search fashion.
The issue is that I can't reassign the search queue (children) because it's borrowed and doesn't live long enough.
https://gist.github.com/varshard/3874803cd035e27facb67c59e89c3c1c#file-binary_tree-rs-L39
How can I correct this?
use std::fmt::Display;
type Branch<'a, T> = Option<Box<Node<'a, T>>>;
struct Node<'a, T: PartialOrd + Display> {
value: &'a T,
left: Branch<'a, T>,
right: Branch<'a, T>
}
impl<'a, T: PartialOrd + Display> Node<'a, T> {
fn insert(&mut self, value: &'a T) {
let target_node = if value > self.value { &mut self.right } else { &mut self.left };
match target_node {
Some(ref mut node) => node.insert(value),
None => {
let new_node = Node{ value: value, left: None, right: None};
*target_node = Some(Box::new(new_node))
}
}
}
fn display(&'a self) {
let mut children: Vec<Option<&Node<'a, T>>> = Vec::new();
children.push(Some(self));
while children.len() > 0 {
for child in &children {
match child {
Some(node) => {
print!("{} ", node.value);
},
None => {
print!(" ")
}
}
}
println!("");
// Error: children doesn't live long enough;
children = self.to_vec(&children);
}
}
fn to_vec(&self, nodes: &'a Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
let mut children: Vec<Option<&Node<'a, T>>> = Vec::new();
for node_option in nodes {
match node_option {
Some(node) => {
match &node.left {
Some(left) => {
children.push(Some(left));
match &node.right {
Some(right) => {
children.push(Some(right));
},
None => {
children.push(None);
}
}
},
None => {
children.push(None);
match &node.right {
Some(right) => {
children.push(Some(right));
},
None => {
children.push(None);
}
}
}
}
},
None => {}
}
}
children
}
}
fn main() {
let root_val = 5;
let mut root = Node{ value: &root_val, left: None, right: None };
root.insert(&3);
root.insert(&4);
root.insert(&1);
root.insert(&6);
root.display();
}

Copying my answer from this reddit comment:
There's a way to directly fix your problem, but I think there are better options for making the code easier to write and understand. For the direct fix, you can make some lifetime adjustments. Instead of
fn to_vec(&self, nodes: &'a Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
You need:
fn to_vec<'b>(&self, nodes: &Vec<Option<&'b Node<'a, T>>>) -> Vec<Option<&'b Node<'a, T>>>
What's the difference there? In the first case we're saying that nodes is a &'a Vec. That is, a borrow of a Vec that lives as long as the value references inside your tree. That's a long time to live, and it's what the compiler's getting angry about.
Now, if you just take the 'a off of that &Vec, the compiler complains about something else:
|
42 | fn to_vec(&self, nodes: &Vec<Option<&Node<'a, T>>>) -> Vec<Option<&Node<'a, T>>> {
| ------------ -------------------------
| |
| this parameter and the return type are declared with different lifetimes...
...
76 | children
| ^^^^^^^^ ...but data from `nodes` is returned here
Maybe this is the error that pushed you to put the 'a on the &Vec in the first place. We need to solve it a different way. The important thing to understand here is that the return value doesn't contain references directly into the nodes vector, but it does contain copies of the nodes vector's contents, the &Node references. We need to tell the compiler that even though the nodes reference doesn't live very long, its contents do live longer. That's why we create the new lifetime 'b in my fix above.
This is objectively very confusing. Personally, I prefer to avoid solving these tricky problems, by just keeping things alive longer instead of reasoning about exactly how long they live. The source of the difficulty is that we're destroying the children vector on line 39. If we were able to keep it around, and just keep emptying it and refilling it, Rust would give us a much easier time. Have you considered using a std::collections::VecDeque instead of a Vec here? You could construct it once outside of your while-loop, and then you could pass &mut children around, without worrying very much about its lifetime. I think a queue is usually the go-to data structure for a breadth-first traversal, with new children added to the back, and the traversal itself reading from the front.

Related

Rust: Implement AVL Tree and error: thread 'main' panicked at 'already borrowed: BorrowMutError'

I have the following tree structure:
use std::cell::RefCell;
use std::rc::Rc;
use std::cmp;
use std::cmp::Ordering;
type AVLTree<T> = Option<Rc<RefCell<TreeNode<T>>>>;
#[derive(Debug, PartialEq, Clone)]
struct TreeSet<T: Ord> {
root: AVLTree<T>,
}
impl<T: Ord> TreeSet<T> {
fn new() -> Self {
Self {
root: None
}
}
fn insert(&mut self, value: T) -> bool {
let current_tree = &mut self.root;
while let Some(current_node) = current_tree {
let node_key = &current_node.borrow().key;
match node_key.cmp(&value) {
Ordering::Less => { let current_tree = &mut current_node.borrow_mut().right; },
Ordering::Equal => {
return false;
}
Ordering::Greater => { let current_tree = &mut current_node.borrow_mut().left; },
}
}
*current_tree = Some(Rc::new(RefCell::new(TreeNode {
key: value,
left: None,
right: None,
parent: None
})));
true
}
}
#[derive(Clone, Debug, PartialEq)]
struct TreeNode<T: Ord> {
pub key: T,
pub parent: AVLTree<T>,
left: AVLTree<T>,
right: AVLTree<T>,
}
fn main() {
let mut new_avl_tree: TreeSet<u32> = TreeSet::new();
new_avl_tree.insert(3);
new_avl_tree.insert(5);
println!("Tree: {:#?}", &new_avl_tree);
}
Building with cargo build is fine, but when I run cargo run, I got the below error:
thread 'main' panicked at 'already borrowed: BorrowMutError', src\libcore\result.rs:1165:5
note: run with RUST_BACKTRACE=1 environment variable to display a backtrace. error: process didn't
exit successfully: target\debug\avl-tree.exe (exit code: 101)
If i just call insert(3), it will be fine and my tree gets printed correctly. However, if I insert(5) after insert(3), I will get that error.
How do I fix that?
Manually implementing data structures such as linked list, tree, graph are not task for novices, because of memory safety rules in language. I suggest you to read Too Many Linked Lists tutorial, which discusses how to implement safe and unsafe linked lists in Rust right way.
Also read about name shadowing.
Your error is that inside a cycle you try to borrow mutable something which is already borrowed as immutable.
let node_key = &current_node.borrow().key; // Borrow as immutable
match node_key.cmp(&value) {
Ordering::Less => { let current_tree = &mut current_node.borrow_mut().right; }, // Create a binding which will be immediately deleted and borrow as mutable.
And I recommend you to read Rust book to learn rust.
First let us correct your algorithm. The following lines are incorrect:
let current_tree = &mut current_node.borrow_mut().right;
...
let current_tree = &mut current_node.borrow_mut().left;
Both do not reassign a value to current_tree but create a new (unused) one (#Inline refers to it as Name shadowing). Remove the let and make current_tree mut.
Now we get a compiler error temporary value dropped while borrowed. Probably the compiler error message did mislead you. It tells you to use let to increase the lifetime, and this would be right if you used the result in the same scope, but no let can increase the lifetime beyond the scope.
The problem is that you cannot pass out a reference to a value owned by a loop (as current_node.borrow_mut.right). So it would be better to use current_tree as owned variable. Sadly this means that many clever tricks in your code will not work any more.
Another problem in the code is the multiple borrow problem (your original runtime warning is about this). You cannot call borrow() and borrow_mut() on the same RefCell without panic(that is the purpose of RefCell).
So after finding the problems in your code, I got interested in how I would write the code. And now that it is written, I thought it would be fair to share it:
fn insert(&mut self, value: T) -> bool {
if let None = self.root {
self.root = TreeSet::root(value);
return true;
}
let mut current_tree = self.root.clone();
while let Some(current_node) = current_tree {
let mut borrowed_node = current_node.borrow_mut();
match borrowed_node.key.cmp(&value) {
Ordering::Less => {
if let Some(next_node) = &borrowed_node.right {
current_tree = Some(next_node.clone());
} else {
borrowed_node.right = current_node.child(value);
return true;
}
}
Ordering::Equal => {
return false;
}
Ordering::Greater => {
if let Some(next_node) = &borrowed_node.left {
current_tree = Some(next_node.clone());
} else {
borrowed_node.left = current_node.child(value);
return true;
}
}
};
}
true
}
//...
trait NewChild<T: Ord> {
fn child(&self, value: T) -> AVLTree<T>;
}
impl<T: Ord> NewChild<T> for Rc<RefCell<TreeNode<T>>> {
fn child(&self, value: T) -> AVLTree<T> {
Some(Rc::new(RefCell::new(TreeNode {
key: value,
left: None,
right: None,
parent: Some(self.clone()),
})))
}
}
One will have to write the two methods child(value:T) and root(value:T) to make this compile.

Borrowed value does not live long enough when adding to a binary tree built on RefCell

I tried to implement an add operation in a binary tree:
use std::cell::RefCell;
use std::cmp::PartialOrd;
type Link<T> = RefCell<Option<Box<Node<T>>>>;
struct Node<T> {
key: T,
left: Link<T>,
right: Link<T>,
}
struct Tree<T> {
root: Link<T>,
}
impl<T> Node<T> {
fn new(val: T) -> Self {
Node {
key: val,
left: RefCell::new(None),
right: RefCell::new(None),
}
}
}
impl<T: PartialOrd> Tree<T> {
fn new() -> Self {
Tree {
root: RefCell::new(None),
}
}
fn add(&self, val: T) {
let mut next = self.root.borrow();
let node = Box::new(Node::new(val));
match next.as_ref() {
None => {
self.root.replace(Some(node));
()
}
Some(root_ref) => {
let mut prev = root_ref;
let mut cur: Option<&Box<Node<T>>> = Some(root_ref);
while let Some(node_ref) = cur {
prev = node_ref;
if node.key < node_ref.key {
next = node_ref.left.borrow();
} else {
next = node_ref.right.borrow();
}
cur = next.as_ref();
}
if node.key < prev.key {
prev.left.replace(Some(node));
} else {
prev.right.replace(Some(node));
}
}
}
}
}
fn main() {}
I don't understand why the next variable doesn't live long enough:
error[E0597]: `next` does not live long enough
--> src/main.rs:36:15
|
36 | match next.as_ref() {
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
error[E0597]: `next` does not live long enough
--> src/main.rs:51:27
|
51 | cur = next.as_ref();
| ^^^^ borrowed value does not live long enough
...
60 | }
| - `next` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
next lives for the entire scope of the add function and, in my opinion, other variables containing references to it are dropped before next has dropped.
The compiler says that "values in a scope are dropped in the opposite order they are created", suggesting that there is another way to declare variables and to solve this problem, but I don't know how.
The problem I see is that in order to update a leaf node of your tree you have to hold a reference to each intermediate step, not only its parent, because all the links up to the root node must be kept alive while you are updating the value. And Rust lifetimes just cannot do that.
That is, Rust cannot do that in a loop, but it can do that in a recursive function, and a tree is best implemented with a recursive function.
Naturally, your recursive struct is Node, not Tree, but something like this could work (there are many ways to get the borrows to work):
impl<T: PartialOrd> Node<T> {
fn add(&self, val: T) {
let mut branch = if val < self.key {
self.left.borrow_mut()
} else {
self.right.borrow_mut()
};
if let Some(next) = &*branch {
next.add(val);
return;
}
//Separated from the if let so that branch is not borrowed.
*branch = Some(Box::new(Node::new(val)));
}
}
And then, in impl Tree just relay the work to this one.
The code may be simplified a bit if, as other people noted, you get rid of the Tree vs Node and the RefCell...

Iterating through a recursive structure using mutable references and returning the last valid reference

I'm trying to recurse down a structure of nodes, modifying them, and then returning the last Node that I get to. I solved the problems with mutable references in the loop using an example in the non-lexical lifetimes RFC. If I try to return the mutable reference to the last Node, I get a use of moved value error:
#[derive(Debug)]
struct Node {
children: Vec<Node>,
}
impl Node {
fn new(children: Vec<Self>) -> Self {
Self { children }
}
fn get_last(&mut self) -> Option<&mut Node> {
self.children.last_mut()
}
}
fn main() {
let mut root = Node::new(vec![Node::new(vec![])]);
let current = &mut root;
println!("Final: {:?}", get_last(current));
}
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
let temp = current;
println!("{:?}", temp);
match temp.get_last() {
Some(child) => { current = child },
None => break,
}
}
current
}
Gives this error
error[E0382]: use of moved value: `*current`
--> test.rs:51:5
|
40 | let temp = current;
| ---- value moved here
...
51 | current
| ^^^^^^^ value used here after move
|
= note: move occurs because `current` has type `&mut Node`, which does not implement the `Copy` trait
If I return the temporary value instead of breaking, I get the error cannot borrow as mutable more than once.
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
let temp = current;
println!("{:?}", temp);
match temp.get_last() {
Some(child) => { current = child },
None => return temp,
}
}
}
error[E0499]: cannot borrow `*temp` as mutable more than once at a time
--> test.rs:47:28
|
43 | match temp.get_last() {
| ---- first mutable borrow occurs here
...
47 | None => return temp,
| ^^^^ second mutable borrow occurs here
48 | }
49 | }
| - first borrow ends here
How can I iterate through the structure with mutable references and return the last Node? I've searched, but I haven't found any solutions for this specific problem.
I can't use Obtaining a mutable reference by iterating a recursive structure because it gives me a borrowing more than once error:
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
let temp = current;
println!("{:?}", temp);
match temp.get_last() {
Some(child) => current = child,
None => current = temp,
}
}
current
}
This is indeed different from Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time. If we look at the answer there, modified a bit, we can see that it matches on a value and is able to return the value that was matched on in the terminal case. That is, the return value is an Option:
fn back(&mut self) -> &mut Option<Box<Node>> {
let mut anchor = &mut self.root;
loop {
match {anchor} {
&mut Some(ref mut node) => anchor = &mut node.next,
other => return other, // transferred ownership to here
}
}
}
Your case is complicated by two aspects:
The lack of non-lexical lifetimes.
The fact that you want to take a mutable reference and "give it up" in one case (there are children) and not in the other (no children). This is conceptually the same as this:
fn maybe_identity<T>(_: T) -> Option<T> { None }
fn main() {
let name = String::from("vivian");
match maybe_identity(name) {
Some(x) => println!("{}", x),
None => println!("{}", name),
}
}
The compiler cannot tell that the None case could (very theoretically) continue to use name.
The straight-forward solution is to encode this "get it back" action explicitly. We create an enum that returns the &mut self in the case of no children, a helper method that returns that enum, and rewrite the primary method to use the helper:
enum LastOrNot<'a> {
Last(&'a mut Node),
NotLast(&'a mut Node),
}
impl Node {
fn get_last_or_self(&mut self) -> LastOrNot<'_> {
match self.children.is_empty() {
false => LastOrNot::Last(self.children.last_mut().unwrap()),
true => LastOrNot::NotLast(self),
}
}
fn get_last(mut current: &mut Node) -> &mut Node {
loop {
match { current }.get_last_or_self() {
LastOrNot::Last(child) => current = child,
LastOrNot::NotLast(end) => return end,
}
}
}
}
Note that we are using all of the techniques exposed in both Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in? and Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time.
With an in-progress reimplementation of NLL, we can simplify get_last_or_self a bit to avoid the boolean:
fn get_last_or_self(&mut self) -> LastOrNot<'_> {
match self.children.last_mut() {
Some(l) => LastOrNot::Last(l),
None => LastOrNot::NotLast(self),
}
}
The final version of Polonius should allow reducing the entire problem to a very simple form:
fn get_last(mut current: &mut Node) -> &mut Node {
while let Some(child) = current.get_last() {
current = child;
}
current
}
See also:
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
Cannot obtain a mutable reference when iterating a recursive structure: cannot borrow as mutable more than once at a time

Search for Successor of BST node, "clone to satisfy borrow checker" disaster

I am trying to implement a BST in Rust. My struct looks like this:
pub struct Node<T> {
key: T,
parent: Option<Box<Node<T>>>,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}
I am working on a method for finding the successor of a current node. After a prolonged fight with the borrow checker, I made it work, but it now looks like this:
//If right node exists - successor is a min node in it.
//Else - go up a parent node. If parent is None, no successor.
//If origin was parent's left node - parent is a successor.
//Else - go up another level.
pub fn succ(&self) -> Option<Box<Node<T>>> {
match self.right {
Some(ref node) => Some(node.min()),
None => {
let mut origin = Box::new(self.clone()); //To match types
let mut parent = origin.parent.clone(); //`Node<T>` not a copy type
loop {
let parent_node = match parent.clone() {
Some(node) => node,
None => break,
};
let right_of_parent = match parent_node.clone().right {
Some(node) => node,
None => break,
};
if *origin != *right_of_parent {
break;
}
origin = parent_node;
parent = origin.parent.clone();
}
parent
}
}
}
If I remove all the .clone()s, the compiler starts crying with "partial moved value" and "cannot assign because borrowed" errors. Is there a way to make this code more idiomatic and less of a cloning hell?
UPD:
Wanted to post the solution I ended up with.
First of all, above code doesn't work, as the parent field contained not a reference, but a copy of a parent node. So in the end the question turned into "how to implement a reference to a parent node".
I considered the answer below, some books and relevant answers and in the end i came to conclusion that it don't worth it for a toy project that I didn't even plan to publish online. I've found not the most efficient, but definitely simpler solution - not to use parent reference at all.
I removed parent field from the structure above and created another structure:
pub struct Tree<T> {
root: Option<Box<Node<T>>>,
}
And now I search for parent from the root of the tree. My succ function now looks like this:
fn succ<'a>(&'a self, node: &'a Node<T>) -> Option<&Node<T>> {
match node.right {
Some(ref rnode) => rnode.min(),
None => {
let mut succ = None;
let mut root = self.root.as_ref();
loop {
root = match root {
Some(ref rootnode) => {
match node.key.cmp(&rootnode.key) {
Ordering::Less => {
succ = Some(&***rootnode);
rootnode.left.as_ref()
}
Ordering::Greater => rootnode.right.as_ref(),
Ordering::Equal => break,
}
}
None => break,
}
}
succ
}
}
}
Welcome to Rust and Stack Overflow!
The main issue here is Node definition:
pub struct Node<T> {
key: T,
parent: Option<Box<Node<T>>>,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}
In Rust, Box<T> owns the value rather than being a pointer which can alias. You wouldn't be a able to create any non-trivial trees.
Instead of Box, you could try the reference counted Rc<T>. You can use Weak pointers for the parent links to avoid keeping them alive:
use std::rc::{Rc,Weak};
pub struct Node<T> {
key: T,
parent: Option<Weak<Node<T>>>,
left: Option<Rc<Node<T>>>,
right: Option<Rc<Node<T>>>,
}
Once this is sorted, you're not using references. Each time you do something like:
let mut parent = origin.parent; //.clone();
where in your version origin.parent is of type Option<Box<Node<T>>>, you're trying to move that Option field out of origin - hence why you had to add the clone() (which clones the node inside the Box, not just the pointer!). However, you don't really want to move out; you just want a reference to it, like:
let parent = &origin.parent;
Or do the None check at the same time:
match origin.parent {
Some(ref parent_ptr) => { ... },
None => { ... }
}
I hope this helps!

wrestling with borrow checker

I'm new to Rust. As a learning exercise I'm trying to make a basic binary tree. This is what I have so far:
fn main() {
let data = vec![6,1,2,3,4,5];
let mut root = Node::<i32> { value: data[0], left: None, right: None };
for val in data {
createAndInsert::<i32>(&root, val);
}
println!("Root value: {}", root.value);
}
fn createAndInsert<T: PartialOrd>(mut root: &Node<T>, value: T) {
let mut n = Node::<T> { value: value, left: None, right: None };
insert::<T>(&root, &n);
}
fn insert<T: PartialOrd>(mut curr: &Node<T>, new: &Node<T>) {
if new.value > curr.value {
match curr.right {
Some(ref n) => insert(n, new),
None => curr.right = Some(Box::new(*new))
}
} else {
match curr.left {
Some(ref n) => insert(n, new),
None => curr.left = Some(Box::new(*new))
}
}
}
struct Node<T: PartialOrd> {
value: T,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}
The compiler errors I'm getting:
test.rs:21:48: 21:52 error: cannot move out of borrowed content
test.rs:21 None => curr.right = Some(Box::new(*new))
^~~~
test.rs:26:47: 26:51 error: cannot move out of borrowed content
test.rs:26 None => curr.left = Some(Box::new(*new))
^~~~
test.rs:21:21: 21:54 error: cannot assign to immutable field `curr.right`
test.rs:21 None => curr.right = Some(Box::new(*new))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test.rs:26:21: 26:53 error: cannot assign to immutable field `curr.left`
test.rs:26 None => curr.left = Some(Box::new(*new))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 4 previous errors
I've got myself tangled in all the refs and muts and &'s and *'s and I'm not sure how to get out. Where am I going wrong?
You have two problems:
Cannot move out of borrowed context: see Cannot move out of borrowed content when borrowing a generic type for an explanation.
Cannot assign to immutable field: you only have a &Node<T>; to modify the Node you need a &mut Node<T>. mut curr in the pattern merely makes the binding mutable, meaning that you can assign a new value to curr. You can’t, however, modify the contents of what curr refers to. Propagate the &-to-&mut conversion throughout the code and it’ll work.
Since you are new to Rust it might help to see how I would have written it:
struct Node<T> {
value: T,
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}
impl<T> Node<T> {
fn new(x: T) -> Node<T> {
Node { value: x, left: None, right: None }
}
fn boxed(x: T) -> Box<Node<T>> {
Box::new(Node::new(x))
}
}
fn insert<T: PartialOrd>(root: &mut Option<Box<Node<T>>>, new: Box<Node<T>>) {
if let Some(ref mut rbx) = *root {
if new.value < rbx.value {
insert(&mut rbx.left, new);
} else {
insert(&mut rbx.right, new);
}
} else {
*root = Some(new);
}
}
fn main() {
let data = vec![6,1,2,3,4,5];
let mut root = None;
for val in data {
insert(&mut root, Node::boxed(val));
}
println!("Root value: {}", root.unwrap().value);
}
I realize that this is more of an exercise but keep in mind that this kind of data structure should not grow beyond a certain tree depth since it might otherwise cause the stack to overflow when the nodes are recursivly deallocated.

Resources