Expected struct `std::boxed::Box`, found `i32` - rust

I am trying to instantiate an object of a BSTNode struct.
But when I try to use the insert method I've implemented I am getting an error saying Expected struct 'std::boxed::Box' found 'i32', but inside the function my parameters are '&mut self' and 'i32', and to use the func from main I do something like that:
let mut root: Option<Box<BSTNode>> = Some(Box::new(BSTNode {
value: 0,
left: None,
right: None,
}));
root.insert(15);
but the insert func generates the error above.
BST Insert func:
pub fn insert(&mut self, val: i32) {
if val <= self.value {
match self.left {
//If there are no nodes on the left, insert a new heap-allocated BSTNode holding the value passed to the fn
None => {
self.left = Some(Box::new(BSTNode {
value: val,
left: None,
right: None,
}))
}
//If there's a node found on the left, recursively call the fn again on the node found.
Some(ref mut node) => node.insert(val),
}
} else {
match self.right {
//If there are no nodes on the right, insert a new heap-allocated BSTNode holding the value passed to the fn
None => {
self.right = Some(Box::new(BSTNode {
value: val,
left: None,
right: None,
}))
}
//If there's a node found on the right, recursively call the fn again on the node found.
Some(ref mut node) => node.insert(val),
}
}
}
BSTNode struct:
pub struct BSTNode {
pub value: i32,
//Hold a possibly-nullable pointer to a heap-allocated object -BSTNode
pub left: Option<Box<BSTNode>>,
pub right: Option<Box<BSTNode>>,
}
What am I missing? why can't I use the insert func properly?

Related

Cannot borrow as mutable, getting a mutable reference from a borrowed value [duplicate]

This question already has answers here:
How to handle "temporary value dropped" error when adapting Box-based tree structure to Rc+RefCell?
(2 answers)
Closed last month.
I was following this other post: Understanding Rust `Rc<RefCell<_>>` where op tried implementing a tree with Box and was successful in doing it but then tried implementing it with Rc and RefCell and found issues. The accepted answer compiles but doesn't work because it doesn't add nodes to the root. I tried updating the accepted answer a bit to try and get it to work but wasn't able to. Basically I'm trying to get mutable references in the loop and I can't because I borroed an immutable reference. But then if a borrow_mut() I get that value is a private field, so I'm assuming I can't access any properties of the contained value if it is a mutable reference?
What should I do to get this code to work?
use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;
use std::fmt;
#[derive(Debug, Clone)]
pub(crate) struct TreeBox<T> {
root: Option<Box<NodeBox<T>>>,
}
#[derive(Debug, Clone)]
struct NodeBox<T> {
value: T,
left: Option<Box<NodeBox<T>>>,
right: Option<Box<NodeBox<T>>>,
}
impl<T: Ord> TreeBox<T> {
fn new() -> Self {
Self { root: None }
}
pub fn insert(&mut self, value: T) -> bool {
let mut node = &mut self.root;
while let Option::Some(current_node) = node {
match current_node.value.cmp(&value) {
Ordering::Less => node = &mut current_node.right,
Ordering::Equal => return false,
Ordering::Greater => node = &mut current_node.left,
}
}
*node = Option::Some(Box::new(NodeBox {
value,
left: Option::None,
right: Option::None,
}));
return true;
}
}
#[derive(Debug, Clone)]
pub(crate) struct Tree<T> {
root: Option<Rc<RefCell<Node<T>>>>,
}
#[derive(Debug, Clone, PartialEq)]
struct Node<T> {
value: T,
left: Option<Rc<RefCell<Node<T>>>>,
right: Option<Rc<RefCell<Node<T>>>>,
}
impl<T: Ord + fmt::Debug> Tree<T> {
fn new() -> Self {
Self { root: None }
}
pub fn insert(&mut self, value: T) -> bool {
let mut node = &mut self.root;
while let Some(current_node) = node {
let current_node = current_node.borrow();
let cmp = current_node.value.cmp(&value);
let new_node = match cmp {
Ordering::Less => &mut current_node.left,
Ordering::Equal => return false,
Ordering::Greater => &mut current_node.right,
};
node = new_node;
}
// let mut node = &mut node;
*node = Some(Rc::new(RefCell::new(Node {
value,
left: None,
right: None,
})));
println!("node: {:?}", node);
true
}
}
fn main() {
let mut tree_box = TreeBox::new();
tree_box.insert(1);
tree_box.insert(2);
tree_box.insert(3);
let mut tree = Tree::new();
tree.insert(1);
tree.insert(2);
tree.insert(3);
println!("TreeBox: {:?}", tree_box);
println!("Tree: {:?}", tree);
}
The accepted answer compiles but doesn't work because it doesn't add nodes to the root.
You are right, and fixing the original solution, here a version that add the root node correctly:
pub fn insert(&mut self, value: T) -> bool {
//if no root, just create one
let mut node = if let Some(root) = &self.root {
Rc::clone(root)
} else {
self.root = Some(Rc::new(RefCell::new(Node {
value,
left: None,
right: None,
})));
return true;
};
loop {
let current_node = Rc::clone(&node);
let mut current_node = RefCell::borrow_mut(&current_node);
let cmp = current_node.value.cmp(&value);
let next_node = match cmp {
Ordering::Less => &mut current_node.left,
Ordering::Equal => return false,
Ordering::Greater => &mut current_node.right,
};
if let Some(next_node) = next_node {
node = Rc::clone(next_node);
} else {
*next_node = Some(Rc::new(RefCell::new(Node {
value,
left: None,
right: None,
})));
println!("node: {:?}", node);
return true;
}
}
}
Basically I'm trying to get mutable references in the loop and I can't because I borroed an immutable reference.
The problem is slightly different. what happens is that you can't walk this Rc<RefCell> tree, at least not interactively like this, because the "borrow" of such structures need to be keep while you are working with it. And your implementation releases the "borrow" after each loop.
But then if a borrow_mut() I get that value is a private field, so I'm
assuming I can't access any properties of the contained value if it is
a mutable reference?
Not really, what is happening here is that you are not calling the function RefCell::borrow_mut that returns a RefMut<Node>, you are in fact calling <Rc as BorrowMut>::borrow_mut that returns &mut RefMut<...>. And by accessing the value you are trying the access the private field value from RefCell, not Node.
Notice that in my implementation I explicitly called RefCell::borrow_mut, that fixes this issue.

Traverse through binary tree

use std::cell::RefCell;
use std::rc::Rc;
#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
pub val: i32,
pub left: Option<Rc<RefCell<TreeNode>>>,
pub right: Option<Rc<RefCell<TreeNode>>>,
}
impl TreeNode {
#[inline]
pub fn new(val: i32) -> Self {
TreeNode {
val,
left: None,
right: None,
}
}
pub fn invalid_path_error(self) {
panic!("Invalid path");
}
pub fn insert(&mut self, directions: &[&str], val: i32) {
let mut cur_node = &mut None;
let l = directions.len();
if directions[0] == "left" {
cur_node = &mut self.left;
}
if directions[0] == "right" {
cur_node = &mut self.right;
}
for dir in &directions[1..] {
let mut n;
if *dir == "left" {
if let Some(z) = cur_node {
n = &mut z.borrow_mut().left;
} else {
panic!("Invalid path");
}
}
if *dir == "right" {
if let Some(z) = cur_node {
n = &mut z.borrow_mut().right;
} else {
panic!("Invalid path");
}
}
cur_node = n;
}
//cur_node = Some(Rc::new(RefCell::new(TreeNode::new(2))));
}
}
I am trying to learn rust by solving some leet code questions. I am trying to implement insert function for binary tree. This is the struct given in leet code. I am trying to implement insert by pass list of strings for path For eg. go left , right , left etc. After traversing at the end I will add new node. I am trying to use cur node as a temp pointer and want to change it with each string. But every time I get this error - " temporary value dropped while borrowed consider using a let binding to create a longer lived value ". How can I fix this and implement insert ?
cargo check -
Here's a solution that replaces Rc<RefCell<_>> with Box<_>. Generally you only need to reach for Rc when multiple people will want ownership over the underlying data. In this case, each node is only owned by one other node, so Box is preferable.
This solution iterates through the tree to find the last node, then uses the last direction to assign to the correct child node. No checks are implemented to make sure that the nodes along the path exist or that an existing node isn't being overwritten.
#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
pub val: i32,
pub left: Option<Box<TreeNode>>,
pub right: Option<Box<TreeNode>>,
}
impl TreeNode {
#[inline]
pub fn new(val: i32) -> Self {
TreeNode {
val,
left: None,
right: None,
}
}
pub fn insert(&mut self, directions: &[&str], val: i32) {
let mut cur_node = self;
let len = directions.len();
let mut directions = directions.into_iter().copied();
for direction in directions.by_ref().take(len - 1) {
let child_node = match direction {
"left" => &mut cur_node.left,
"right" => &mut cur_node.right,
_ => panic!("invalid direction {direction}"),
};
cur_node = child_node.as_mut().expect("invalid path").as_mut();
}
let new_node = Some(Box::new(TreeNode::new(val)));
match directions.next().unwrap() {
"left" => cur_node.left = new_node,
"right" => cur_node.right = new_node,
direction # _ => panic!("invalid direction {direction}"),
}
}
}
fn main() {
let mut tree = TreeNode::new(0);
tree.insert(&["left"], 1);
tree.insert(&["right"], 2);
tree.insert(&["left", "left"], 2);
tree.insert(&["right", "left"], 3);
println!("{:#?}", tree);
}
Prints
TreeNode {
val: 0,
left: Some(
TreeNode {
val: 1,
left: Some(
TreeNode {
val: 2,
left: None,
right: None,
},
),
right: None,
},
),
right: Some(
TreeNode {
val: 2,
left: Some(
TreeNode {
val: 3,
left: None,
right: None,
},
),
right: None,
},
),
}

How to use methods of a different struct?

I have a BSTNode struct with an insert function in it:
pub struct BSTNode {
pub value: i32,
pub left: Option<Box<BSTNode>>,
pub right: Option<Box<BSTNode>>,
}
impl BSTNode {
pub fn insert(&mut self, val: i32) {
if val <= self.value {
match self.left {
None => {
self.left = Some(Box::new(BSTNode {
value: val,
left: None,
right: None,
}))
}
Some(ref mut node) => node.insert(val),
}
} else {
match self.right {
None => {
self.right = Some(Box::new(BSTNode {
value: val,
left: None,
right: None,
}))
}
Some(ref mut node) => node.insert(val),
}
}
}
}
I also have a BST struct to store that Node
struct BST {
node: Option<BSTNode>,
}
Is it possible to call the insert func implemented on the BSTNode through the BST struct?
What I mean is, that in the main.rs I could do this:
let mut root = BST::BST::new();
root.insert(5) // getting error obviously because method does not exist on BST struct.
Is it possible to kind of point to that BSTNode method what I call 'insert' through the BST struct?
I tried to just implement this method in the BST struct instead of keeping it in the BSTNode struct, but I am encountering a lot of problems, although that will be my last resort.
Keep it simple stupid solution: Just make an explicit delegator.
impl BST {
pub fn insert(&mut self, val: i32) {
if let Some(node) = self.node.as_mut() {
node.insert(val);
}
}
}
No need to reimplement anything, and the extra function call will almost certainly get inlined out unless you go out of your way to impede optimizations.

Data structure is not modified when calling a method that takes `self`

I am writing a binary tree structure, and I have problems at the insert function. After calling the function to insert data in my node, the node is not modified.
use std::ptr;
#[derive(Clone, Copy)]
struct Node<T> {
data: Option<T>,
left: *mut Node<T>,
right: *mut Node<T>,
}
impl<T> Node<T> {
pub fn new(data: T) -> Node<T> {
Node {
data: Some(data),
left: ptr::null_mut(),
right: ptr::null_mut(),
}
}
pub fn insert(mut self, data: T) {
let tmp = self.data.unwrap();
self.data = None;
self.left = &mut Node::new(data);
self.right = &mut Node::new(tmp);
}
}
impl<T: std::fmt::Display> std::fmt::Display for Node<T>
where T: std::fmt::Debug
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self.data {
Some(ref x) => {
write!(f, "Node data: {}, left: {}, right: {}", x,
if self.left.is_null() {"null"} else {"not null"},
if self.right.is_null() {"null"} else {"not null"},
)
}
None => {
write!(f, "Node data: None, left: {}, right: {}",
if self.left.is_null() {"null"} else {"not null"},
if self.right.is_null() {"null"} else {"not null"},
)
}
}
}
}
fn main() {
let mut root: Node<i32> = Node::new(32);
println!("Root before insert : {}", root);
root.insert(42);
println!("Root after insert: {}", root);
}
And a trace of execution
Root before insert : Node data: 32, left: null, right: null
Root after insert : Node data: 32, left: null, right: null
My node is not modified after the function insert. What can I do to solve this?
Since you appear to be quite confused, let's get you started!
First of all, there is no reason to use raw pointers. Furthermore, I advise AGAINST using Copy as it just hides ownership issues. Finally, it's much easier to derive Debug than implement the formatting manually (and it allows experimenting with the layout of the struct in a more automated fashion).
#[derive(Debug)]
struct Node<T> {
data: Option<T>, // are you sure about using Option here?
left: Option<Box<Node<T>>>,
right: Option<Box<Node<T>>>,
}
So, instead of raw pointers, we use a Box pointer which we place into an Option to handle the null case.
The construction is now:
impl<T> Node<T> {
fn new(data: T) -> Node<T> {
Node {
data: Some(data),
left: None,
right: None,
}
}
}
Nothing outstanding, let's move on to insert:
impl<T> Node<T> {
fn insert(&mut self, data: T) {
let current = self.data.take().expect("Cannot insert in empty node!");
self.left = Some(Box::new(Node::new(current)));
self.right = Some(Box::new(Node::new(data)));
}
}
And we can move on to the display (using Debug with "{:?}"):
fn main() {
let mut root: Node<i32> = Node::new(32);
println!("Root before insert : {:?}", root);
root.insert(42);
println!("Root after insert: {:?}", root);
}
And it works!

Cannot build a delete function for a binary search tree in Rust because the borrowed value does not live long enough

I am struggling to code a delete method for a BST:
use std::cmp::Ordering::{Less,Equal,Greater};
type Child = Option<Box<Node>>;
#[derive(Debug)]
struct Node {
val: i32,
left: Child,
right: Child,
}
impl Node {
fn new(val: i32) -> Node {
Node {
val: val,
left: None,
right: None,
}
}
fn delete(&mut self, val: i32) {
//find the node for deletion
let mut node: &mut Node = self;
loop {
match val.cmp(&self.val) {
Less => {
if self.left.is_some() {
node = &mut (self.left.as_mut().unwrap());
} else {
break;
}
}
Equal => break,
Greater => node = panic!("nyi"),
}
}
// once found, check if the node has children and delete accordingly
}
}
fn main() {
let mut node = Node::new(10);
node.right = Some(Box::new(Node::new(20)));
}
I have tried loads of different techniques using recursion and iteration but the borrow checker complains. For example:
error: borrowed value does not live long enough
node = &mut (self.left.as_mut().unwrap());
^~~~~~~~~~~~~~~~~~~~~~~~~~~
Is it possible to write a delete function using safe Rust?
This recursive solution compiles:
use std::cmp::Ordering::{Less,Equal,Greater};
type Child = Option<Box<Node>>;
#[derive(Debug)]
struct Node {
val: i32,
left: Child,
right: Child,
}
impl Node {
fn new(val: i32) -> Node {
Node {
val: val,
left: None,
right: None,
}
}
fn delete(&mut self, val: i32) {
fn find_node_to_delete(node: &mut Node, val: i32) -> Option<&mut Node> {
match val.cmp(&node.val) {
Less => {
if let Some(ref mut left) = node.left {
find_node_to_delete(left, val)
} else {
None
}
}
Equal => Some(node),
Greater => unimplemented!(),
}
}
//find the node for deletion
let node = find_node_to_delete(self, val);
// once found, check if the node has children and delete accordingly
}
}
fn main() {
let mut node = Node::new(10);
node.right = Some(Box::new(Node::new(20)));
}

Resources