nekolib/ds/
bicremental_median.rs1use std::collections::BTreeMap;
4use std::fmt::Debug;
5
6#[derive(Clone, Debug, Eq, PartialEq)]
21pub struct BicrementalMedian<T: Ord + Clone> {
22 lower_len: usize,
23 upper_len: usize,
24 lower: BTreeMap<T, usize>,
25 upper: BTreeMap<T, usize>,
26}
27
28impl<T: Ord + Clone> BicrementalMedian<T> {
29 pub fn new() -> Self {
30 Self {
31 lower_len: 0,
32 upper_len: 0,
33 lower: BTreeMap::new(),
34 upper: BTreeMap::new(),
35 }
36 }
37 pub fn insert(&mut self, x: T) {
38 if self.lower_len == 0 {
39 self.lower.insert(x, 1);
40 self.lower_len += 1;
41 } else if self.lower_len == self.upper_len {
42 if &x <= self.upper.iter().next().unwrap().0 {
44 *self.lower.entry(x).or_insert(0) += 1;
46 } else {
47 self.rotate_to_lower();
49 *self.upper.entry(x).or_insert(0) += 1;
50 }
51 self.lower_len += 1;
52 } else {
53 if self.lower.iter().next_back().unwrap().0 < &x {
55 *self.upper.entry(x).or_insert(0) += 1;
57 } else {
58 self.rotate_to_upper();
60 *self.lower.entry(x).or_insert(0) += 1;
61 }
62 self.upper_len += 1;
63 }
64 }
65 pub fn remove(&mut self, x: &T) -> bool {
66 if self.lower_len == 0 {
67 false
68 } else if self.lower_len == self.upper_len {
69 if self.upper.contains_key(x) {
71 self.remove_from_upper(x, false);
73 return true;
74 }
75 if self.lower.contains_key(x) {
76 self.remove_from_lower(x, true);
78 return true;
79 }
80 false
81 } else {
82 if self.lower.contains_key(x) {
84 self.remove_from_lower(x, false);
86 return true;
87 }
88 if self.upper.contains_key(x) {
89 self.remove_from_upper(x, true);
91 return true;
92 }
93 false
94 }
95 }
96 pub fn median(&self) -> Option<&T> {
97 if self.lower_len == 0 {
98 None
99 } else {
100 Some(self.lower.iter().next_back().unwrap().0)
101 }
102 }
103}
104
105impl<T: Ord + Clone> BicrementalMedian<T> {
106 fn rotate_to_lower(&mut self) {
107 let (x, k) =
108 self.upper.iter().next().map(|(x, &k)| (x.clone(), k)).unwrap();
109 if k == 1 {
110 self.upper.remove(&x);
111 } else {
112 *self.upper.get_mut(&x).unwrap() -= 1;
113 }
114 *self.lower.entry(x).or_insert(0) += 1;
115 }
116 fn rotate_to_upper(&mut self) {
117 let (x, k) = self
118 .lower
119 .iter()
120 .next_back()
121 .map(|(x, &k)| (x.clone(), k))
122 .unwrap();
123 if k == 1 {
124 self.lower.remove(&x);
125 } else {
126 *self.lower.get_mut(&x).unwrap() -= 1;
127 }
128 *self.upper.entry(x).or_insert(0) += 1;
129 }
130 fn remove_from_lower(&mut self, x: &T, rotate: bool) {
131 if self.lower[x] == 1 {
132 self.lower.remove(x);
133 } else {
134 *self.lower.get_mut(x).unwrap() -= 1;
135 }
136 if rotate {
137 self.rotate_to_lower();
138 self.upper_len -= 1;
139 } else {
140 self.lower_len -= 1;
141 }
142 }
143 fn remove_from_upper(&mut self, x: &T, rotate: bool) {
144 if self.upper[x] == 1 {
145 self.upper.remove(x);
146 } else {
147 *self.upper.get_mut(x).unwrap() -= 1;
148 }
149 if rotate {
150 self.rotate_to_upper();
151 self.lower_len -= 1;
152 } else {
153 self.upper_len -= 1;
154 }
155 }
156}
157
158#[test]
159fn test_simple() {
160 let n = 32768;
161 let mut f =
162 std::iter::successors(Some(296), |&x| Some((x * 258 + 185) % 397))
163 .map(|x| x & 15);
164 let mut bucket = vec![0; 8];
165 let mut bm = BicrementalMedian::<usize>::new();
166 for _ in 0..n {
167 let x = f.next().unwrap();
168 let (remove, x) = (x & 8 != 0, x & 7);
169 if remove && bucket[x] > 0 {
170 bucket[x] -= 1;
171 bm.remove(&x);
172 } else {
173 bucket[x] += 1;
174 bm.insert(x);
175 }
176 let mut naive = vec![];
177 for i in 0..8 {
178 naive.extend(std::iter::repeat(i).take(bucket[i]));
179 }
180 assert_eq!(bm.median(), naive.get(naive.len().wrapping_sub(1) / 2));
181 }
182}