How to read & modify value of node in linked tree?

684 views Asked by At

I'm struggling with the implementation of tree structure in Rust. Particularly, getting and modifying the node's value. What is idiomatic way to work with the value?

Note: the implementation is given and cannot be changed.

use std::rc::Rc;
use std::cell::RefCell;

// Definition for a binary tree node.
#[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
    }
  }
}

fn main() {
    let mut root = Some(Rc::new(RefCell::new(TreeNode::new(1))));
    println!("{:?}", root.unwrap().borrow().val); // cannot infer type for type parameter `Borrowed`
    root.unwrap().get_mut().val = 2; // cannot borrow data in an `Rc` as mutable
}
2

There are 2 answers

0
Evgeni Nabokov On BEST ANSWER
let root = Some(Rc::new(RefCell::new(TreeNode::new(1))));
let mut v = RefCell::borrow(root.as_ref().unwrap()).val) // Too verbose, but I do not know a brief way.
println!("{}", v); // 1
root.as_ref().unwrap().borrow_mut().val += 1;
v = RefCell::borrow(root.as_ref().unwrap()).val)
println!("{}", v); // 2

0
pretzelhammer On

You can safely unwrap the value if you know it's Some(T). The Rc<T> should work like a transparent container that derefs on method calls, so you can generally treat an Rc<T> as a T, or specifically a RefCell<T> in your case, then you can interact with the value inside the RefCell using the borrow and borrow_mut methods. Example:

use std::rc::Rc;
use std::cell::RefCell;

// Definition for a binary tree node.
#[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
    }
  }
}


fn main() {
    let mut root = Some(Rc::new(RefCell::new(TreeNode::new(1))));
    let mut root = root.unwrap();
    println!("{:?}", root.borrow().val); // read access
    root.borrow_mut().val = 2; // write access
}

playground

See also Unwrap and access T from an Option<Rc<RefCell<T>>>