简体   繁体   中英

How to have multiple references for a single node in a tree structure using Rust

Trying to create a tree in rust with the following struct:

pub struct Node{
    pub children: Vec<Box<Node>>,
    pub parent: Option<Box<Node>>,
    pub value: f32,
    //.....
}

To build a new node the following function is used:

pub fn build_node(parent: Option<Box<Node>>)-> Node{
    Node{
        children: vec![],
        parent,
        value: 0.0,

    }
}

When trying to add nodes, for example with:

let mut root_nd = tree::build_node(None, 5, state);
let mut next_nd = tree::build_node(Some(Box::new(root_nd)), 2);
root_nd.children.push(Box::new(next_nd));

There will be errors, because I am borrowing for example root_nd and then trying to add next_nd to the root.children list, and even if there wasnt this error I would still need to have a reference for next_nd after adding it to the children of root_nd . I know that in rust it is not possible to have several mutable references simultaneously for the same element. So the question is how is it possible to make a tree-like data structure, with bi-directional references in rust? In my head this is a conflict since rust does not want multiple references but I need a node in the middle of the tree to be referenced by both his parent node and his children nodes.

I've been meddling with trees in Rust for quite a bit recently. To work with trees in rust, you will need Rc (A single-threaded reference-counting pointer) so that you can have multiple ownership. And you'll also need RefCell to enable interior mutability since multiple mutable references are not allowed by the compiler. With Rc and RefCell , you can define your TreeNode as following:

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

pub struct TreeNode {
    pub children: Vec<Rc<RefCell<TreeNode>>>,
    pub parent: Option<Rc<RefCell<TreeNode>>>,
    pub value: f32,
}

And here is one way to create two nodes that references each other:

impl TreeNode {
  #[inline]
  pub fn new(value: f32) -> Self {
    TreeNode {
      value,
      children: vec![],
      parent: None
    }
  }
}

let mut root_nd = Rc::new(RefCell::new(TreeNode::new(5.0)));
let mut child_nd = Rc::new(RefCell::new(TreeNode::new(2.0)));

child_nd.borrow_mut().parent = Some(root_nd.clone());  // use Rc::clone to create a new reference to root_nd
root_nd.borrow_mut().children.push(child_nd.clone());

Since we use Rc::clone to create a new reference to the node, root_nd and child_nd are not consumed and can still be accessed in later program.

More examples on Trees in Rust:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM