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.
Related
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(¤t_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.
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?
I've been trying to teach myself some Rust lately and wanted to practice a bit by implementing a simple linked list. I took some inspiration from the Rust library's linked list and tried to replicate the parts I already understood. Also I decided to make it singly-linked for now.
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Node<T> {
fn new(element: T) -> Self {
Node {
element: element,
next: None,
}
}
fn append(&mut self, element: Box<Node<T>>) {
self.next = Some(element);
}
}
pub struct LinkedList<T> {
head: Option<Box<Node<T>>>,
tail: Option<Box<Node<T>>>,
len: u32,
}
impl<T> LinkedList<T> {
pub fn new() -> Self {
head: None,
tail: None,
len: 0,
}
pub fn push(&mut self, element: T) {
let node: Box<Node<T>> = Box::new(Node::new(element));
match self.tail {
None => self.head = Some(node),
Some(mut ref tail) => tail.append(node),
}
self.tail = Some(node);
self.len += 1;
}
pub fn pop(&mut self) -> Option<T> {
//not implemented
}
pub fn get(&self, index: u32) -> Option<T> {
//not implemented
}
}
This is what I've got so far; from what I understand, the problem with this code is that the Box can not have more than one reference to it in order to preserve memory safety.
So when I set the list head to node in
None => self.head = Some(node),
I can't then go ahead and set
self.tail = Some(node);
later, am I correct so far in my understanding? What would be the correct way to do this? Do I have to use Shared like in the library or is there a way in which the Box or some other type can be utilized?
Your issue is that you are attempting to use a value (node) after having moved it; since Box<Node<T>> does not implement Copy, when you use it in the match expression:
match self.tail {
None => self.head = Some(node),
Some(ref mut tail) => tail.append(node),
}
node is moved either to self.head or to self.tail and can no longer be used later. Other than reading the obligatory Learning Rust With Entirely Too Many Linked Lists to see the different ways in which you can implement linked lists in Rust, I suggest that you first do some more research in the field of Rust's basic concepts, especially:
Ownership
References and Borrowing
What are move semantics?
You can go with something simpler than that, only using your nodes
use std::fmt;
struct Payload {
id: i32,
value: i32,
}
impl fmt::Display for Payload {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({}, {})", self.id, self.value)
}
}
struct Node<T> {
element: T,
next: Option<Box<Node<T>>>,
}
impl<T> Node<T> where T: std::fmt::Display{
fn new(element: T) -> Self {
Node {
element: element,
next: None,
}
}
fn append(&mut self, element: T) {
match &mut self.next {
None => {let n = Node {
element: element,
next: None,
};
self.next = Some(Box::new(n));
},
Some(ref mut x) => x.append(element),
}
}
fn list(& self) {
println!("{}", self.element);
match &self.next {
None => {},
Some(x) => x.list(),
}
}
}
fn main(){
let mut h = Node::new(Payload {id:1, value:1});
h.append(Payload {id:2, value:2});
h.append(Payload {id:3, value:3});
h.append(Payload {id:4, value:4});
h.append(Payload {id:5, value:5});
h.list();
h.append(Payload {id:6, value:6});
h.list();
}
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!
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)));
}