treap_map/
node.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5use super::{
6    config::{ConsoliableWeight, Direction, TreapMapConfig},
7    update::{OpResult, TreapNodeUpdate},
8};
9
10use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
11use std::mem;
12
13/// A node in a treap-map data structure.
14///
15/// The `Node` struct represents a node in a treap-map and contains various
16/// key-value pairs and metadata required for the proper functioning and
17/// maintenance of the treap-map. Direct modification of these fields is not
18/// recommended outside of the `TreapMap::update` function, as this function
19/// correctly maintains the integrity of the treap-map.
20#[cfg_attr(test, derive(Debug, PartialEq, Eq))]
21pub struct Node<C: TreapMapConfig> {
22    /// The key exposed externally. Used for key-based searches within the
23    /// treap-map.
24    pub key: C::SearchKey,
25
26    /// The value stored in the node.
27    pub value: C::Value,
28
29    /// The sorting key for the treap-map. If the type is `()`, the
30    /// `search_key` is used for sorting.
31    pub sort_key: C::SortKey,
32
33    /// The weight of the node, used by the treap-map to maintain accumulated
34    /// weights.
35    pub weight: C::Weight,
36
37    /// The sum of the weights of this node and its descendants. Maintained
38    /// internally for efficient operations.
39    pub(crate) sum_weight: C::Weight,
40
41    /// A priority value used by the treap algorithm, typically a random
42    /// number.
43    priority: u64,
44
45    /// The left child of the node in the treap-map structure.
46    pub(crate) left: Option<Box<Node<C>>>,
47
48    /// The right child of the node in the treap-map structure.
49    pub(crate) right: Option<Box<Node<C>>>,
50}
51
52impl<C: TreapMapConfig> Node<C> {
53    pub fn new(
54        key: C::SearchKey, value: C::Value, sort_key: C::SortKey,
55        weight: C::Weight, priority: u64,
56    ) -> Node<C> {
57        Node {
58            key,
59            value,
60            sort_key,
61            sum_weight: weight.clone(),
62            weight,
63            priority,
64            left: None,
65            right: None,
66        }
67    }
68
69    pub(crate) fn get(
70        &self, sort_key: &C::SortKey, key: &C::SearchKey,
71    ) -> Option<&C::Value> {
72        match C::next_node_dir((sort_key, key), (&self.sort_key, &self.key)) {
73            None => Some(&self.value),
74            Some(Direction::Left) => self.left.as_ref()?.get(sort_key, key),
75            Some(Direction::Right) => self.right.as_ref()?.get(sort_key, key),
76        }
77    }
78
79    pub(crate) fn update_inner<U: TreapNodeUpdate<C>>(
80        maybe_node: &mut Option<Box<Node<C>>>, updater: U,
81    ) -> (U::Ret, bool, bool) {
82        // Compare the key
83        let next_node_dir = if let Some(node) = maybe_node {
84            C::next_node_dir(updater.treap_key(), (&node.sort_key, &node.key))
85        } else {
86            None
87        };
88
89        // Goto the next node or apply on the current node (if hit)
90        let (ret, update_weight, mut update_priority) = match next_node_dir {
91            None => {
92                let update_result = updater.update_node(maybe_node.as_mut());
93                Node::process_update_result::<U>(maybe_node, update_result)
94            }
95
96            Some(dir) => {
97                let node = maybe_node.as_mut().unwrap();
98                let next_node = match dir {
99                    Direction::Left => &mut node.left,
100                    Direction::Right => &mut node.right,
101                };
102                Node::update_inner(next_node, updater)
103            }
104        };
105
106        // Update the sum_weight and priority inneeded.
107        if let Some(node) = maybe_node.as_mut() {
108            if update_weight {
109                node.update_weight()
110            }
111            if let (Some(dir), true) = (next_node_dir, update_priority) {
112                match dir {
113                    Direction::Left
114                        if node.left.as_ref().map_or(false, |left| {
115                            node.priority < left.priority
116                        }) =>
117                    {
118                        node.right_rotate();
119                    }
120                    Direction::Right
121                        if node.right.as_ref().map_or(false, |right| {
122                            node.priority < right.priority
123                        }) =>
124                    {
125                        node.left_rotate();
126                    }
127                    _ => {
128                        update_priority = false;
129                    }
130                }
131            }
132        }
133        (ret, update_weight, update_priority)
134    }
135
136    fn process_update_result<U: TreapNodeUpdate<C>>(
137        maybe_node: &mut Option<Box<Node<C>>>,
138        result: OpResult<C, U::Ret, U::DeleteRet>,
139    ) -> (U::Ret, bool, bool) {
140        match result {
141            OpResult::Noop(ret) => (ret, false, false),
142            OpResult::Updated { update_weight, ret } => {
143                (ret, update_weight, false)
144            }
145            OpResult::InsertOnVacant { insert, ret } => {
146                // `maybe_node` should be empty here. So we ignore the replaced
147                // value.
148                let _ = mem::replace(maybe_node, Some(insert));
149                (ret, true, true)
150            }
151            OpResult::Delete(delete_ret) => {
152                let deleted_node = if maybe_node.is_some() {
153                    Some(Node::delete(maybe_node))
154                } else {
155                    None
156                };
157                let ret = U::handle_delete(deleted_node, delete_ret);
158                (ret, true, true)
159            }
160        }
161    }
162
163    // Rotate the current node to the leaf and delete it
164    fn delete(mustbe_node: &mut Option<Box<Node<C>>>) -> Box<Self> {
165        use Direction::*;
166        let node = mustbe_node.as_mut().unwrap();
167        let next_root = match (&node.left, &node.right) {
168            (None, None) => {
169                // Both is None, remove current node directly
170                return mem::take(mustbe_node).unwrap();
171            }
172            (None, Some(_)) => Right,
173            (Some(_), None) => Left,
174            (Some(left), Some(right)) => {
175                if left.priority < right.priority {
176                    Right
177                } else {
178                    Left
179                }
180            }
181        };
182
183        let res = match next_root {
184            Right => {
185                // node.right must be `Some` before left rotate
186                node.left_rotate();
187                // node.left must be `Some` after left rotate
188                Node::delete(&mut node.left)
189            }
190            Left => {
191                // node.left must be `Some` before right rotate
192                node.right_rotate();
193                // node.right must be `Some` after right rotate
194                Node::delete(&mut node.right)
195            }
196        };
197
198        node.update_weight();
199        res
200    }
201
202    //    X              Y
203    //   / \            / \
204    //  A   Y    <=    X   C
205    //     / \        / \
206    //    B   C      A   B
207
208    fn right_rotate(self: &mut Box<Node<C>>) {
209        //     Y  <- self
210        //    / \
211        //   X   C
212        //  / \
213        // A   B
214
215        let y_node = self;
216        let mut x_node = mem::take(&mut y_node.left).unwrap();
217
218        //    Y  <- self      X
219        //   / \             / \
220        //  .   C           A   B
221
222        // For efficiency, must swap pointer, instead of node data
223        mem::swap::<Box<Node<C>>>(y_node, &mut x_node);
224        let (x_node, mut y_node) = (y_node, x_node);
225
226        //    Y               X  <- self
227        //   / \             / \
228        //  .   C           A   B
229
230        mem::swap::<Option<Box<Node<C>>>>(&mut x_node.right, &mut y_node.left);
231
232        //    Y               X  <- self
233        //   / \             / \
234        //  B   C           A   .
235
236        y_node.update_weight();
237        x_node.right = Some(y_node);
238
239        //    X
240        //   / \
241        //  A   Y
242        //     / \
243        //    B   C
244
245        x_node.update_weight();
246    }
247
248    //    X              Y
249    //   / \            / \
250    //  A   Y    =>    X   C
251    //     / \        / \
252    //    B   C      A   B
253    fn left_rotate(self: &mut Box<Node<C>>) {
254        //    X   <- self
255        //   / \
256        //  A   Y
257        //     / \
258        //    B   C
259
260        let x_node = self;
261        let mut y_node = mem::take(&mut x_node.right).unwrap();
262
263        //    X  <- self      Y
264        //   / \             / \
265        //  A   .           B   C
266
267        // For efficiency, must swap pointer, instead of node data
268        mem::swap::<Box<Node<C>>>(x_node, &mut y_node);
269        // Also swap variable name
270        let (y_node, mut x_node) = (x_node, y_node);
271
272        //    X               Y  <- self
273        //   / \             / \
274        //  A   .           B   C
275
276        mem::swap::<Option<Box<Node<C>>>>(&mut y_node.left, &mut x_node.right);
277
278        //    X               Y  <- self
279        //   / \             / \
280        //  A   B           .   C
281
282        x_node.update_weight();
283        y_node.left = Some(x_node);
284
285        //      Y  <- self
286        //     / \
287        //    X   C
288        //   / \
289        //  A   B
290
291        y_node.update_weight();
292    }
293
294    pub(crate) fn update_weight(&mut self) {
295        self.sum_weight = self.weight.clone();
296        if let Some(left) = &self.left {
297            self.sum_weight.accure(&left.sum_weight);
298        }
299        if let Some(right) = &self.right {
300            self.sum_weight.accure(&right.sum_weight);
301        }
302    }
303
304    pub fn sum_weight(&self) -> C::Weight { self.sum_weight.clone() }
305
306    #[cfg(any(test, feature = "testonly_code"))]
307    pub(crate) fn assert_consistency(&self)
308    where C::Weight: Eq + std::fmt::Debug {
309        let mut weight = self.weight.clone();
310
311        if let Some(left) = self.left.as_ref() {
312            weight.accure(&left.sum_weight);
313            assert!(left.priority <= self.priority);
314            left.assert_consistency();
315            assert_eq!(
316                C::next_node_dir(
317                    (&left.sort_key, &left.key),
318                    (&self.sort_key, &self.key)
319                ),
320                Some(Direction::Left)
321            );
322        }
323        if let Some(right) = self.right.as_ref() {
324            weight.accure(&right.sum_weight);
325            assert!(right.priority <= self.priority);
326            right.assert_consistency();
327            assert_eq!(
328                C::next_node_dir(
329                    (&right.sort_key, &right.key),
330                    (&self.sort_key, &self.key)
331                ),
332                Some(Direction::Right)
333            );
334        }
335
336        assert_eq!(weight, self.sum_weight);
337    }
338}
339
340impl<C: TreapMapConfig> MallocSizeOf for Node<C>
341where
342    C::SearchKey: MallocSizeOf,
343    C::SortKey: MallocSizeOf,
344    C::Value: MallocSizeOf,
345    C::Weight: MallocSizeOf,
346{
347    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
348        self.key.size_of(ops)
349            + self.sort_key.size_of(ops)
350            + self.value.size_of(ops)
351            + self.weight.size_of(ops)
352            + self.sum_weight.size_of(ops)
353            + self.left.size_of(ops)
354            + self.right.size_of(ops)
355    }
356}