A Cactus Stack or Parent Pointer Tree is a stack where nodes in the stack have pointers to their parent so the stack is climbable in multiple ways.
I'm trying to implement a mutable Cactus Stack in Rust based off of this immutable implementation using the Rc<RefCell<T>>
pattern to pass around shared memory:
use std::rc::Rc;
use std::cell::RefCell;
#[derive(Clone, Default)]
pub struct Cactus<T> {
node: Option<Rc<RefCell<Node<T>>>>,
}
#[derive(Clone)]
pub struct Node<T> {
val: Rc<RefCell<T>>,
parent: Option<Rc<RefCell<Node<T>>>>,
len: usize,
}
impl<T> Cactus<T> {
pub fn new() -> Cactus<T> {
Cactus { node: None }
}
pub fn is_empty(&self) -> bool {
self.node.is_none()
}
pub fn len(&self) -> usize {
self.node.as_ref().map_or(0, |x| x.borrow().len)
}
pub fn child(&self, val: T) -> Cactus<T> {
Cactus {
node: Some(Rc::new(RefCell::new(Node {
val: Rc::new(RefCell::new(val)),
parent: self.node.clone(),
len: self.node.as_ref().map_or(1, |x| x.borrow().len + 1),
}))),
}
}
pub fn parent(&self) -> Option<Cactus<T>> {
self.node.as_ref().map(|n| Cactus {
node: n.borrow().parent.clone(),
})
}
pub fn val(&mut self) -> Option<Rc<RefCell<T>>> {
self.node.map(|n| n.borrow_mut().val.clone())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simple() {
let r = Cactus::new();
assert!(r.is_empty());
assert_eq!(r.len(), 0);
assert!(r.val().is_none());
assert!(r.parent().is_none());
let r2 = r.child(2);
assert!(!r2.is_empty());
assert_eq!(r2.len(), 1);
assert_eq!(*r2.val().unwrap(), 2);
let r3 = r2.parent().unwrap();
assert_eq!(r3.is_empty(), true);
assert_eq!(r3.len(), 0);
let r4 = r.child(3);
assert_eq!(r4.len(), 1);
assert_eq!(*r4.val().unwrap(), 3);
let r5 = r4.parent().unwrap();
assert!(r5.is_empty());
let r6 = r4.child(4);
assert_eq!(r6.len(), 2);
assert_eq!(*r6.val().unwrap(), 4);
assert_eq!(*r6.parent().unwrap().val().unwrap(), 3);
}
}
My issue is getting the val
from nodes:
error[E0308]: mismatched types
--> src/main.rs:64:9
|
64 | assert_eq!(*r2.val().unwrap(), 2);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::cell::RefCell`, found integral variable
|
= note: expected type `std::cell::RefCell<{integer}>`
found type `{integer}`
= note: this error originates in a macro outside of the current crate
error[E0308]: mismatched types
--> src/main.rs:70:9
|
70 | assert_eq!(*r4.val().unwrap(), 3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::cell::RefCell`, found integral variable
|
= note: expected type `std::cell::RefCell<{integer}>`
found type `{integer}`
= note: this error originates in a macro outside of the current crate
error[E0308]: mismatched types
--> src/main.rs:75:9
|
75 | assert_eq!(*r6.val().unwrap(), 4);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::cell::RefCell`, found integral variable
|
= note: expected type `std::cell::RefCell<{integer}>`
found type `{integer}`
= note: this error originates in a macro outside of the current crate
error[E0308]: mismatched types
--> src/main.rs:76:9
|
76 | assert_eq!(*r6.parent().unwrap().val().unwrap(), 3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::cell::RefCell`, found integral variable
|
= note: expected type `std::cell::RefCell<{integer}>`
found type `{integer}`
= note: this error originates in a macro outside of the current crate