cartesian_tree/
tree.rs

1//! Cartesian Tree
2//!
3
4type Nodes<'a, T> = Vec<CartesianTreeNode<'a, T>>;
5type Stack = Vec<CartesianNodeIdx>;
6type Actions = Vec<CartesianTreeAction>;
7
8/// An index into a collection of cartesian tree nodes
9#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone)]
10struct CartesianNodeIdx(usize);
11
12impl<'a, T: Ord> std::ops::Index<CartesianNodeIdx> for Vec<CartesianTreeNode<'a, T>> {
13    type Output = CartesianTreeNode<'a, T>;
14    fn index(&self, index: CartesianNodeIdx) -> &Self::Output {
15        &self[index.0]
16    }
17}
18
19impl<'a, T: Ord> std::ops::IndexMut<CartesianNodeIdx> for Vec<CartesianTreeNode<'a, T>> {
20    fn index_mut(&mut self, index: CartesianNodeIdx) -> &mut Self::Output {
21        &mut self[index.0]
22    }
23}
24
25#[derive(Debug)]
26struct CartesianTreeNode<'a, T: Ord> {
27    /// A reference to the array value that this node represents
28    value: &'a T,
29
30    /// The locations of the children and parent of this node.
31    left_child_idx: Option<CartesianNodeIdx>,
32    right_child_idx: Option<CartesianNodeIdx>,
33}
34
35impl<'a, T: Ord> From<&'a T> for CartesianTreeNode<'a, T> {
36    fn from(value: &'a T) -> Self {
37        CartesianTreeNode {
38            value,
39            left_child_idx: None,
40            right_child_idx: None,
41        }
42    }
43}
44
45/// When constructing a cartesian tree, we either
46/// push a node to or pop a node from a stack.
47/// We keep track of these actions because we can
48/// use them to generate the cartesian tree number.
49#[derive(Debug, Eq, PartialEq)]
50enum CartesianTreeAction {
51    Push,
52    Pop,
53}
54
55/// A cartesian tree is a heap ordered binary tree
56/// derived from some underlying array. An in-order
57/// traversal of the tree yields the underlying array.
58#[derive(Debug)]
59pub struct CartesianTree<'a, T: Ord> {
60    nodes: Vec<CartesianTreeNode<'a, T>>,
61    root_idx: Option<CartesianNodeIdx>,
62    action_profile: Vec<CartesianTreeAction>,
63}
64
65// To create the cartesian tree, we pop the stack until either
66// it's empty or the element atop the stack has a smaller value
67// than the element we are currently trying to add to the stack.
68// Once we break out of the `pop` loop, we make the item we popped
69// a left child of the new item we are adding. Additionally, we make
70// this new item a right/left child of the item atop the stack
71impl<'a, T: Ord> From<&'a [T]> for CartesianTree<'a, T> {
72    fn from(underlying: &'a [T]) -> Self {
73        let len = underlying.len();
74        let mut nodes = Vec::with_capacity(len);
75        let mut stack = Vec::<CartesianNodeIdx>::with_capacity(len);
76        let mut action_profile = Vec::with_capacity(len * 2);
77        for (idx, value) in underlying.iter().enumerate() {
78            nodes.push(value.into());
79            let node_idx = CartesianNodeIdx(idx);
80            Self::add_node_to_cartesian_tree(&mut nodes, &mut stack, &mut action_profile, node_idx);
81        }
82        let root_idx = stack.first().map(|min| min.clone());
83        CartesianTree {
84            nodes,
85            root_idx,
86            action_profile,
87        }
88    }
89}
90
91impl<'a, T: Ord> CartesianTree<'a, T> {
92    pub fn in_order_traversal(&self) -> Vec<&T> {
93        let mut res = Vec::with_capacity(self.nodes.len());
94        self.traversal_helper(&self.root_idx, &mut res);
95        res
96    }
97
98    fn traversal_helper(&self, cur_idx: &Option<CartesianNodeIdx>, res: &mut Vec<&'a T>) {
99        let nodes = &self.nodes;
100        match cur_idx {
101            None => {}
102            Some(cur_sub_root) => {
103                self.traversal_helper(&nodes[cur_sub_root.clone()].left_child_idx, res);
104                res.push(&nodes[cur_sub_root.clone()].value);
105                self.traversal_helper(&nodes[cur_sub_root.clone()].right_child_idx, res);
106            }
107        }
108    }
109
110    /// Calculates the cartesian tree number of this tree
111    /// using the sequence of `push` and `pop` operations
112    /// stored in the `action_profile`. Note that calculating this
113    /// value only makes sense when the underlying array is small.
114    /// More specifically, this procedure assumes that the underlying
115    /// array has at most 32 items. This makes sense in our context
116    /// since we're mostly interested in the cartesian tree numbers
117    /// of RMQ blocks
118    pub fn cartesian_tree_number(&self) -> u64 {
119        let mut number = 0;
120        let mut offset = 0;
121        for action in &self.action_profile {
122            if action == &CartesianTreeAction::Push {
123                number |= 1 << offset;
124            }
125            offset += 1;
126        }
127        number
128    }
129
130    /// Adds the node at the given idx into the tree by wiring up the
131    /// child and parent pointers. it is assumed that the
132    /// node has already been added to `nodes` the list of nodes.
133    /// This procedure returns an optional index value
134    /// that is populated if the root changed.
135    fn add_node_to_cartesian_tree(
136        nodes: &mut Nodes<T>,
137        stack: &mut Stack,
138        actions: &mut Actions,
139        new_idx: CartesianNodeIdx,
140    ) -> () {
141        let mut last_popped = None;
142        loop {
143            match stack.last() {
144                None => break,
145                Some(top_node_idx) => {
146                    // If the new node is greater than the value atop the stack,
147                    // we make the new node a right child of that value
148                    if nodes[top_node_idx.clone()].value < nodes[new_idx.clone()].value {
149                        nodes[top_node_idx.clone()].right_child_idx = Some(new_idx.clone());
150                        break;
151                    }
152                    last_popped = stack.pop();
153                    actions.push(CartesianTreeAction::Pop);
154                }
155            }
156        }
157        // We make the last item we popped a left child of the
158        // new node
159        if let Some(last_popped_idx) = last_popped {
160            nodes[new_idx.clone()].left_child_idx = Some(last_popped_idx);
161        }
162        stack.push(new_idx);
163        actions.push(CartesianTreeAction::Push);
164    }
165}
166
167#[test]
168fn test_cartesian_tree() {
169    use pretty_assertions::assert_eq;
170
171    let v = [93, 84, 33, 64, 62, 83, 63];
172    let tree: CartesianTree<'_, _> = v.as_ref().into();
173    assert!(tree.root_idx.is_some());
174    assert_eq!(tree.nodes[tree.root_idx.clone().unwrap()].value, &33);
175    for (&l, &r) in tree.in_order_traversal().into_iter().zip(v.iter()) {
176        assert_eq!(l, r);
177    }
178}