treap_map/config.rs
1use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
2use primitives::Zero;
3use std::{cmp::Ordering, ops::Add};
4
5/// The weight type in a Treap. It is used to perform operations like
6/// calculating sums or maximum values of an interval in logrithmic time over
7/// treap.
8pub trait ConsoliableWeight: Clone + Eq {
9 /// Create a default or 'zero' value for the weight. Consolidating with this
10 /// value should not change the other value.
11 fn empty() -> Self;
12
13 /// Combine two weights into a single one.
14 fn consolidate(a: &Self, b: &Self) -> Self;
15
16 /// Combine another weight into `self`. It allows for implementing more
17 /// efficient in-place consolidation.
18 fn accure(&mut self, other: &Self) {
19 *self = Self::consolidate(&*self, other);
20 }
21}
22
23impl<T: Add<Output = T> + Clone + Zero + Eq> ConsoliableWeight for T {
24 fn empty() -> Self { T::zero() }
25
26 fn consolidate(a: &Self, b: &Self) -> Self { a.clone() + b.clone() }
27
28 fn accure(&mut self, other: &Self) { *self = self.clone() + other.clone() }
29}
30
31#[derive(Clone, PartialEq, Eq, Copy, Debug)]
32/// Represents a dummy version of `ConsolidatableWeight`.
33///
34/// `NoWeight` is a unit struct that doesn't store any data. It is used as a
35/// placeholder or a default implementation in scenarios where a weight
36/// component is required by the interface but not actually needed for the
37/// specific use case.
38pub struct NoWeight;
39
40impl ConsoliableWeight for NoWeight {
41 #[inline]
42 fn empty() -> Self { NoWeight }
43
44 #[inline]
45 fn consolidate(_: &Self, _: &Self) -> Self { NoWeight }
46
47 #[inline]
48 fn accure(&mut self, _other: &Self) {}
49}
50
51/// `TreapMap` is a struct which implements a treap which can be indexed by a
52/// different key (type `SearchKey`). The associate type `SortKey` and
53/// `SearchKey` defines how to order node in treap collaborately.
54///
55/// As the user only needs to provider the `SearchKey` in searching an element,
56/// but the underlying treap is ordered by both `SortKey` and `SearchKey`.
57/// `TreapMap` also maintains `KeyMng` to recover `SortKey` from `SearchKey`. It
58/// could be a `HashMap`.
59///
60/// If `TreapMap` is indexed in the same key as the inside treap. The `SortKey`
61/// can be deprecated to `()` and the `KeyMng` can be deprecated to a unit type.
62/// Since it is compiled through static dispatch, unnecessary operations will be
63/// optimized away.
64pub trait TreapMapConfig: Sized {
65 /// The search key type in the TreapMap, supporting query/remove a node by
66 /// key.
67 type SearchKey;
68 /// The sort key in the treap.
69 type SortKey;
70 /// The stored value.
71 type Value: Clone;
72 /// The external map which can computing `SortKey` from `SearchKey`. If not
73 /// needed, it could be a unit type.
74 type ExtMap: KeyMngTrait<Self>;
75 /// The consolidable weight.
76 type Weight: ConsoliableWeight;
77
78 /// Compare the key.
79 fn next_node_dir(
80 me: (&Self::SortKey, &Self::SearchKey),
81 other: (&Self::SortKey, &Self::SearchKey),
82 ) -> Option<Direction>;
83}
84
85/// Represents the possible directions in a binary tree search based on key
86/// comparisons.
87///
88/// This enum is defined as part of the [`TreapMapConfig`] trait and is used to
89/// determine the direction of traversal in a binary tree during key-based
90/// searches.
91#[derive(Clone, Copy, PartialEq, Eq, Debug)]
92
93pub enum Direction {
94 /// Indicates that the search should proceed to the left child of the
95 /// current node. This direction is typically chosen when the current
96 /// key is greater than the search key.
97 Left,
98
99 /// Indicates that the search should proceed to the right child of the
100 /// current node. This direction is usually selected when the current
101 /// key is less than the search key.
102 Right,
103}
104
105/// Searching in `Treap` requires sort key. This trait manages the relationship
106/// among sort keys, search keys and values in a Treap. This is necessary when
107/// the sort key is not directly derivable from the search key or is not a null
108/// element.
109#[allow(clippy::len_without_is_empty)]
110pub trait KeyMngTrait<C: TreapMapConfig>: Default {
111 /// Invoked when a new key-value pair is changed in the Treap.
112 fn view_update(
113 &mut self, key: &C::SearchKey, value: Option<&C::Value>,
114 old_value: Option<&C::Value>,
115 );
116 /// Number of the keys
117 fn len(&self) -> usize;
118 /// Retrieve the sort key for a given search key.
119 /// Returns `None` if the search key is not in the treap.
120 fn get_sort_key(&self, key: &C::SearchKey) -> Option<C::SortKey>;
121 /// Generate the sort key from a key-value pair.
122 fn make_sort_key(&self, key: &C::SearchKey, value: &C::Value)
123 -> C::SortKey;
124}
125
126/// If `TreapMap` is indexed in the same key as the inside treap, it can be
127/// configed in a simple way.
128pub trait SharedKeyTreapMapConfig {
129 /// The search key in the TreapMap.
130 type Key: Ord;
131 /// The stored value.
132 type Value: Clone;
133 /// The consolidable weight.
134 type Weight: ConsoliableWeight;
135}
136
137impl<T: SharedKeyTreapMapConfig> TreapMapConfig for T {
138 type ExtMap = Counter;
139 type SearchKey = T::Key;
140 type SortKey = ();
141 type Value = T::Value;
142 type Weight = T::Weight;
143
144 #[inline]
145 fn next_node_dir(
146 (_, me): (&(), &Self::SearchKey), (_, other): (&(), &Self::SearchKey),
147 ) -> Option<Direction> {
148 match me.cmp(other) {
149 Ordering::Less => Some(Direction::Left),
150 Ordering::Equal => None,
151 Ordering::Greater => Some(Direction::Right),
152 }
153 }
154}
155#[derive(Default)]
156pub struct Counter(pub usize);
157
158impl<C: TreapMapConfig<SortKey = ()>> KeyMngTrait<C> for Counter {
159 #[inline]
160 fn view_update(
161 &mut self, _key: &C::SearchKey, value: Option<&C::Value>,
162 old_value: Option<&C::Value>,
163 ) {
164 if value.is_some() {
165 self.0 += 1;
166 }
167 if old_value.is_some() {
168 self.0 -= 1
169 }
170 }
171
172 fn len(&self) -> usize { self.0 }
173
174 fn get_sort_key(&self, _key: &C::SearchKey) -> Option<()> { Some(()) }
175
176 fn make_sort_key(
177 &self, _key: &C::SearchKey, _value: &C::Value,
178 ) -> C::SortKey {
179 }
180}
181
182impl MallocSizeOf for Counter {
183 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
184 self.0.size_of(ops)
185 }
186}