dynamization/
sorted_vec.rs

1//! Sorted `Vec`. Can be used as a priority queue or as an associative array. 
2//! __Requires feature `sorted_vec`__.
3//!
4//! Defines an opaque [`SortedVec`] type and two containers:
5//! * [`SVQueue`] analogous to [`BinaryHeap`](alloc::collections::BinaryHeap)
6//! * [`SVMap`] analogous to [`BTreeMap`](alloc::collections::BTreeMap)
7
8
9use crate::*;
10use alloc::vec;
11
12/// An opaque struct with an unspecified interface.
13///
14/// Obviously can't be used directly.
15#[derive(Clone, Debug)]
16pub struct SortedVec<T> {
17    vec: Vec<T>,
18}
19
20enum Branch {
21    A, B, None
22}
23
24impl<T: Ord> Static for SortedVec<T> {
25    fn len(&self) -> usize {
26        self.vec.len()
27    }
28
29    fn merge_with(self, other: Self) -> Self {
30        let a = self.vec;
31        let b = other.vec;
32
33        let mut vec: Vec<T> = Vec::with_capacity(a.len() + b.len());
34        
35        let vec_ptr = vec.as_mut_ptr();
36        let mut i = 0;
37
38        let mut a = a.into_iter();
39        let mut b = b.into_iter();
40
41        let mut maybe_x = a.next();
42        let mut maybe_y = b.next();
43
44        let branch;
45
46        loop {
47            match (maybe_x, maybe_y) {
48                (Some(x), Some(y)) => {
49                    if x < y {
50                        unsafe { vec_ptr.add(i).write(x); }
51                        maybe_x = a.next();
52                        maybe_y = Some(y);
53                    } else {
54                        unsafe { vec_ptr.add(i).write(y); }
55                        maybe_x = Some(x);
56                        maybe_y = b.next();
57                    }
58
59                    i += 1;
60                }
61
62                (Some(x), None) => {
63                    unsafe { vec_ptr.add(i).write(x); }
64                    i += 1;
65                    branch = Branch::A;
66                    break;
67                }
68                
69                (None, Some(y)) => {
70                    unsafe { vec_ptr.add(i).write(y); }
71                    i += 1;
72                    branch = Branch::B;
73                    break;
74                }
75
76                (None, None) => { 
77                    branch = Branch::None;
78                    break; 
79                }
80            }
81        }
82
83        match branch {
84            Branch::A => {
85                for x in a {
86                    unsafe { vec_ptr.add(i).write(x); }
87                    i += 1;
88                }
89            }
90            
91            Branch::B => {
92                for x in b {
93                    unsafe { vec_ptr.add(i).write(x); }
94                    i += 1;
95                }
96            }
97
98            Branch::None => {}
99        }
100
101        assert!(i == vec.capacity());
102        // Safety: the assertion above; also this assertion almost guarantees
103        // that the memory accesses in the loops above (.add(i).write(...))
104        // do not touch unallocated memory.
105        unsafe { vec.set_len(i); }
106
107        SortedVec { vec }
108    }
109}
110
111impl<T> Singleton for SortedVec<T> {
112    type Item = T;
113    
114    fn singleton(item: Self::Item) -> Self {
115        SortedVec { vec: vec![item] }
116    }
117}
118
119impl<T: Ord> core::iter::FromIterator<T> for SortedVec<T> {
120    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
121        let mut vec = iter.into_iter().collect::<Vec<_>>();
122        
123        vec.sort();
124
125        SortedVec { vec }
126    }
127}
128
129
130/// A max-priority queue based on a sorted vector.
131///
132/// Currently provides only basic operations.
133///
134/// Has slow insertions (4-8 times slower than those of 
135/// [`BinaryHeap`](`alloc::collections::BinaryHeap`)) but fast deletions 
136/// (2-3 times faster then [`BinaryHeap`](alloc::collections::BinaryHeap) ones).
137#[derive(Clone, Debug)]
138pub struct SVQueue<T, S = strategy::Binary> {
139    dynamic: Dynamic<SortedVec<T>, S>,
140    len: usize,
141}
142
143
144impl<T: Ord> SVQueue<T> {
145    /// Uses the [`Binary`](strategy::Binary) strategy.
146    pub fn new() -> Self {
147        SVQueue {
148            dynamic: Dynamic::new(),
149            len: 0,
150        }
151    }
152
153    /// Can be used as in 
154    ///
155    /// ```
156    /// # #[cfg(feature="sorted_vec")] {
157    /// # use dynamization::sorted_vec::SVQueue;
158    /// use dynamization::strategy;
159    ///
160    /// let pqueue = SVQueue::<i32>::with_strategy::<strategy::SkewBinary>();
161    /// //                  ^^^^^^^ -- optional if the payload type can be inferred
162    /// # }
163    /// ```
164    ///
165    /// The [`SkewBinary`](strategy::SkewBinary) strategy has the fastest 
166    /// [peeks](SVQueue::peek) and [deletions](SVQueue::pop).
167    pub fn with_strategy<S: Strategy>() -> SVQueue<T, S> {
168        SVQueue {
169            dynamic: Dynamic::new(),
170            len: 0,
171        }
172    }
173}
174
175
176impl<T: Ord, S: Strategy> SVQueue<T, S> {
177    /// Returns the number of elements currently stored.
178    pub fn len(&self) -> usize {
179        self.len
180    }
181
182    /// Returns `self.len() == 0`.
183    pub fn is_empty(&self) -> bool {
184        self.len == 0
185    }
186
187    /// Inserts a new item into the container.
188    pub fn push(&mut self, item: T) {
189        self.dynamic.insert(item);
190        self.len += 1;
191    }
192
193    /// Returns the current maximum.
194    pub fn peek(&self) -> Option<&T> {
195        self.dynamic.units()
196            .filter_map(|unit| unit.vec.last())
197            .max()
198    }
199
200    /// Exclusively returns the current maximum.
201    pub fn peek_mut(&mut self) -> Option<&mut T> {
202        self.dynamic.units_mut()
203            .filter_map(|unit| unit.vec.last_mut())
204            .max()
205    }
206
207    /// Removes the current maximum from the container.
208    pub fn pop(&mut self) -> Option<T> {
209        let best_unit = self.dynamic.units_mut()
210            .max_by(|u1, u2| {
211                u1.vec.last().cmp(&u2.vec.last())
212            });
213
214        match best_unit {
215            None => None,
216
217            Some(unit) => {
218                match unit.vec.pop() {
219                    None => None,
220
221                    Some(x) => {
222                        self.len -= 1;
223                        Some(x)
224                    }
225                }
226            }
227        }
228    }
229}
230
231#[test]
232fn test_svqueue_len() {
233    let some_numbers = vec![1,4,6,2,1,5,7,4,3,2,7,8];
234
235    let mut pqueue = SVQueue::new();
236    let mut counter = 0;
237
238    for x in some_numbers { 
239        pqueue.push(x);
240        counter += 1;
241
242        assert_eq!(pqueue.len(), counter);
243        assert_eq!(pqueue.len(), pqueue.dynamic.len());
244    }
245
246    while !pqueue.is_empty() {
247        pqueue.pop();
248        counter -= 1;
249
250        assert_eq!(pqueue.len(), counter);
251        assert_eq!(pqueue.len(), pqueue.dynamic.len());
252    }
253}
254
255
256
257/// An associative array based on a sorted vector.
258///
259/// Currently provides only basic operations.
260///
261/// Much slower than [`BTreeMap`](`alloc::collections::BTreeMap`) so useful 
262/// only for nonpractical purposes (mainly as an example of implementing 
263/// a dynamized container).
264#[derive(Clone, Debug)]
265pub struct SVMap<K, V, S = strategy::Binary> {
266    dynamic: Dynamic<SortedVec<SVPair<K, V>>, S>,
267    len: usize,
268    free_count: usize,
269}
270
271#[derive(Clone, Debug)]
272struct SVPair<K, V>(K, Option<V>);
273
274impl<K: Ord, V> Ord for SVPair<K, V> {
275    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
276        self.0.cmp(&other.0)
277    }
278}
279
280impl<K: Ord, V> PartialOrd for SVPair<K, V> {
281    fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
282        Some(self.cmp(other))
283    }
284}
285
286impl<K: Ord, V> PartialEq for SVPair<K, V> {
287    fn eq(&self, other: &Self) -> bool {
288        self.0 == other.0
289    }
290}
291
292impl<K: Ord, V> Eq for SVPair<K, V> {}
293
294impl<K: Ord, V> SVMap<K, V> {
295    /// Uses the [`Binary`](strategy::Binary) strategy.
296    pub fn new() -> Self {
297        SVMap {
298            dynamic: Dynamic::new(),
299            len: 0,
300            free_count: 0,
301        }
302    }
303
304    /// Can be used as in 
305    ///
306    /// ```
307    /// # #[cfg(feature="sorted_vec")] {
308    /// # use dynamization::sorted_vec::SVMap;
309    /// use dynamization::strategy;
310    ///
311    /// let svmap = SVMap::<String, i32>::with_strategy::<strategy::SkewBinary>();
312    /// //               ^^^^^^^^^^^^^^^ -- optional if the payload type can be inferred
313    /// # }
314    /// ```
315    pub fn with_strategy<S: Strategy>() -> SVMap<K, V, S> {
316        SVMap {
317            dynamic: Dynamic::new(),
318            len: 0,
319            free_count: 0,
320        }
321    }
322}
323
324
325impl<K: Ord, V, S: Strategy> SVMap<K, V, S> {
326    /// Returns the number of elements currently stored.
327    pub fn len(&self) -> usize {
328        self.len
329    }
330
331    /// Returns `self.len() == 0`.
332    pub fn is_empty(&self) -> bool {
333        self.len == 0
334    }
335
336    fn search<Q: Ord + ?Sized>(&self, key: &Q) -> Option<&SVPair<K, V>> where
337        K: core::borrow::Borrow<Q> 
338    {
339        for unit in self.dynamic.units() {
340            let vec = &unit.vec;
341
342            if let Ok(index) = vec.binary_search_by(|entry| {
343                entry.0.borrow().cmp(key)
344            }) {
345                // Safety: binary search returned Ok
346                return unsafe { Some(vec.get_unchecked(index)) }
347            }
348        }
349
350        None
351    }
352
353    fn search_mut<Q: Ord + ?Sized>(&mut self, key: &Q) -> Option<&mut SVPair<K, V>> where
354        K: core::borrow::Borrow<Q> 
355    {
356        for unit in self.dynamic.units_mut() {
357            let vec = &mut unit.vec;
358
359            if let Ok(index) = vec.binary_search_by(|entry| {
360                entry.0.borrow().cmp(key)
361            }) {
362                // Safety: binary search returned Ok
363                return unsafe { Some(vec.get_unchecked_mut(index)) }
364            }
365        }
366
367        None
368    }
369    
370    /// Searches for an item with a specified key. 
371    ///
372    /// Returns `true` if the item is found.
373    pub fn contains_key<Q: Ord + ?Sized>(&self, key: &Q) -> bool where
374        K: core::borrow::Borrow<Q>
375    {
376        self.search(key).is_some()
377    }
378
379    /// Searches for an item with a specified key. 
380    ///
381    /// Returns a shared reference to the item found or `None`.
382    pub fn get<Q: Ord + ?Sized>(&self, key: &Q) -> Option<&V> where
383        K: core::borrow::Borrow<Q>
384    {
385        self.search(key).map(|entry| entry.1.as_ref()).flatten()
386    }
387
388    /// Searches for an item with a specified key. 
389    ///
390    /// Returns shared references to the key and the value stored or `None` if 
391    /// the item has not been found.
392    pub fn get_key_value<Q: Ord + ?Sized>(&self, key: &Q) -> Option<(&K, &V)> where
393        K: core::borrow::Borrow<Q>
394    {
395        self.search(key).map(|entry| {
396            match &entry.1 {
397                Some(v) => { Some( (&entry.0, v) ) }
398                None => { None }
399            }
400        }).flatten()
401    }
402
403    /// Searches for an item with a specified key. 
404    ///
405    /// Returns an exclusive reference to the item found or `None`.
406    pub fn get_mut<Q: Ord + ?Sized>(&mut self, key: &Q) -> Option<&mut V> where
407        K: core::borrow::Borrow<Q>
408    {
409        self.search_mut(key).map(|entry| entry.1.as_mut()).flatten()
410    }
411
412    /// Inserts a new key-value pair into the map.
413    ///
414    /// Returns the old value if it has been present. __Does not__ update 
415    /// the key in such a case!
416    pub fn insert(&mut self, key: K, value: V) -> Option<V> {
417        if let Some(entry) = self.search_mut(&key) {
418            let result = core::mem::replace(&mut entry.1, Some(value));
419
420            if let None = result {
421                self.len += 1;
422                self.free_count -= 1;
423            }
424
425            result
426        } else {
427            self.dynamic.insert(SVPair(key, Some(value)));
428            self.len += 1;
429            None
430        }
431    }
432   
433
434    const REBUILD_THRESHOLD: usize = 16;
435   
436    /// Removes an item from the container.
437    ///
438    /// Returns the item removed or `None` if the item has not been found.
439    pub fn remove<Q: Ord + ?Sized>(&mut self, key: &Q) -> Option<V> where
440        K: core::borrow::Borrow<Q>
441    {
442        if let Some(entry) = self.search_mut(&key) {
443            let result = core::mem::replace(&mut entry.1, None);
444
445            if let Some(_) = result {
446                self.len -= 1;
447                self.free_count += 1;
448            }
449
450            if self.free_count > self.len && self.len > Self::REBUILD_THRESHOLD {
451                let mut tmp = SVMap::<K, V>::with_strategy::<S>();
452
453                core::mem::swap(self, &mut tmp);
454
455                *self = tmp.into_iter().collect();
456            }
457
458            result
459        } else { None }
460    }
461    
462   
463    /// Removes all elements from the map.
464    pub fn clear(&mut self) {
465        self.dynamic.clear();
466        self.len = 0;
467        self.free_count = 0;
468    }
469}
470
471impl<K: Ord, V, S: Strategy> core::iter::FromIterator<(K, V)> for SVMap<K, V, S> {
472    fn from_iter<I: IntoIterator<Item=(K, V)>>(iter: I) -> Self {
473        let sv = iter
474            .into_iter()
475            .map(|(k,v)| SVPair(k, Some(v)))
476            .collect::<SortedVec<_>>();
477
478        let mut dynamic = Dynamic::new();
479        let len = sv.len();
480        dynamic.add_unit(sv);
481
482        Self {
483            dynamic,
484            len,
485            free_count: 0,
486        }
487    }
488}
489
490
491/// Iterator over key-value pairs for [`SVMap`].
492///
493/// __Does not__ sort the values by key.
494// FIXME: sort entries by key! (or better add a corresponding method)
495pub struct SVMapKV<K, V> {
496    unit_iter: DynamicIntoIter<SortedVec<SVPair<K, V>>>,
497    opt_kv_iter: Option<alloc::vec::IntoIter<SVPair<K, V>>>,
498}
499
500impl<K, V> Iterator for SVMapKV<K, V> {
501    type Item = (K, V);
502
503    fn next(&mut self) -> Option<Self::Item> {
504        loop {
505            if let Some(kv_iter) = &mut self.opt_kv_iter {
506                while let Some(sv_pair) = kv_iter.next() {
507                    if let Some(value) = sv_pair.1 {
508                        return Some( (sv_pair.0, value) );
509                    }
510                }
511            } // kv_iter is empty or absent
512            
513            self.opt_kv_iter = 
514                self.unit_iter.next().map(|sv| sv.vec.into_iter());
515            
516            if let None = self.opt_kv_iter { return None; }
517        }
518    }
519}
520
521
522impl<K: Ord, V, S> core::iter::IntoIterator for SVMap<K, V, S> {
523    type Item = (K, V);
524    type IntoIter = SVMapKV<K, V>;
525
526    fn into_iter(self) -> Self::IntoIter {
527        SVMapKV {
528            unit_iter: self.dynamic.into_iter(),
529            opt_kv_iter: None,
530        }
531    }
532}