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.
109pub trait KeyMngTrait<C: TreapMapConfig>: Default {
110 /// Invoked when a new key-value pair is changed in the Treap.
111 fn view_update(
112 &mut self, key: &C::SearchKey, value: Option<&C::Value>,
113 old_value: Option<&C::Value>,
114 );
115 /// Number of the keys
116 fn len(&self) -> usize;
117 /// Retrieve the sort key for a given search key.
118 /// Returns `None` if the search key is not in the treap.
119 fn get_sort_key(&self, key: &C::SearchKey) -> Option<C::SortKey>;
120 /// Generate the sort key from a key-value pair.
121 fn make_sort_key(&self, key: &C::SearchKey, value: &C::Value)
122 -> C::SortKey;
123}
124
125/// If `TreapMap` is indexed in the same key as the inside treap, it can be
126/// configed in a simple way.
127pub trait SharedKeyTreapMapConfig {
128 /// The search key in the TreapMap.
129 type Key: Ord;
130 /// The stored value.
131 type Value: Clone;
132 /// The consolidable weight.
133 type Weight: ConsoliableWeight;
134}
135
136impl<T: SharedKeyTreapMapConfig> TreapMapConfig for T {
137 type ExtMap = Counter;
138 type SearchKey = T::Key;
139 type SortKey = ();
140 type Value = T::Value;
141 type Weight = T::Weight;
142
143 #[inline]
144 fn next_node_dir(
145 (_, me): (&(), &Self::SearchKey), (_, other): (&(), &Self::SearchKey),
146 ) -> Option<Direction> {
147 match me.cmp(other) {
148 Ordering::Less => Some(Direction::Left),
149 Ordering::Equal => None,
150 Ordering::Greater => Some(Direction::Right),
151 }
152 }
153}
154#[derive(Default)]
155pub struct Counter(pub usize);
156
157impl<C: TreapMapConfig<SortKey = ()>> KeyMngTrait<C> for Counter {
158 #[inline]
159 fn view_update(
160 &mut self, _key: &C::SearchKey, value: Option<&C::Value>,
161 old_value: Option<&C::Value>,
162 ) {
163 if value.is_some() {
164 self.0 += 1;
165 }
166 if old_value.is_some() {
167 self.0 -= 1
168 }
169 }
170
171 fn len(&self) -> usize { self.0 }
172
173 fn get_sort_key(&self, _key: &C::SearchKey) -> Option<()> { Some(()) }
174
175 fn make_sort_key(
176 &self, _key: &C::SearchKey, _value: &C::Value,
177 ) -> C::SortKey {
178 ()
179 }
180}
181
182impl MallocSizeOf for Counter {
183 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
184 self.0.size_of(ops)
185 }
186}