4 ms·
Tree and Node must own subnodes, but node need just to point to parent, it cannot own parent. #[derive(Debug)] struct Node { data: i32, left: Opti
by drran 5y ago
Tree and Node must own subnodes, but node need just to point to parent, it cannot own parent.
#[derive(Debug)]
struct Node {
data: i32,
left: Option<Box<Node>>,
right: Option<Box<Node>>,
parent: Option<*mut Node>,
}
impl Node {
pub fn new_root(data: i32) -> Self {
Node { data, left: None, right: None, parent: None, }
}
pub fn new_leaf(data: i32, parent: *mut Node) -> Self {
Node { data, left: None, right: None, parent: Some(parent), }
}
}
#[derive(Debug)]
struct Tree {
root: Option<Node>,
}
impl Tree {
pub fn new() -> Self {
Tree { root: None }
}
pub fn insert(&mut self, data: i32) -> bool {
match self.root {
Some(ref mut node) => Tree::insert_at(node, data),
None => {
self.root = Some(Node::new_root(data));
true
}
}
}
fn insert_at(current_node: &mut Node, data: i32) -> bool {
match (
current_node.left.as_deref_mut(),
current_node.right.as_deref_mut(),
) {
_ if data == current_node.data => false,
(Some(left_node), _) if data < current_node.data => Tree::insert_at(left_node, data),
(None, _) if data < current_node.data => {
let new_node = Node::new_leaf(data, current_node);
current_node.left = Some(Box::new(new_node));
true
}
(_, Some(right_node)) => Tree::insert_at(right_node, data),
(_, None) => {
let new_node = Node::new_leaf(data, current_node);
current_node.right = Some(Box::new(new_node));
true
}
}
}
}
pub fn main() {
let mut tree = Tree::new();
let data = [5, 3, 65, 123, 6, 11, 3, 1, 5, 42];
for i in data {
tree.insert(i);
}
println!("{:?}", tree);
}
- scotty79 5y agoCould you keep parent reference in Option<Rc<Node>> ?
- eliben 5y ago`Rc` implies ownership, albeit shared one. So if a heap location is held by `Rc`, all reference to it should be either `Rc` or `Weak`. You can't have an `Rc` and a `Box` for the same data, IIUC. A `Box` is unaware of `Rc` and will drop its data when dropped itself.
- eliben 5y agoI had this approach in a draft as well! In fact, I tried this before making all links `*mut Node`. But coding the removal methods turned out to be really hard - I couldn't fight through the borrow checker. So I figured if I already have raw pointers and unsafe blocks, might as well go all the way :)
- drran 5y agoI tried to implement removing of elements from the tree, just as an exercise, and I see no problems with borrow checker at all. I use Rust since version 1.0, so borrow checker is my friend. Rebalancing of the left branch is a bit complicated, so I implemented just detach() method, which takes out the element with it subbranches from the tree. From there, you can implement your favorite deletion method. For production, I will just mark a node as deleted and then compact the tree later, to have predictable timings.