dsa_rust/associative/
avl_tree_map.rs

1/*! A proper sorted map
2
3# About
4This sorted map uses the library's [AVL tree]() as its backing structure, providing _O(log(n))_ search, insert, and delete operations.
5
6# Example
7
8```rust
9    use dsa_rust::associative::avl_tree_map::TreeMap;
10
11    let text = "and the final paragraph clearly came from the heart,
12    or whatever cool yet sensitive organ Sadie kept in place of one.";
13
14    let mut map = TreeMap::<char, usize>::new();
15
16    // SAFETY: This is a thing
17    unsafe {}
18
19    for e in text.chars() {
20        if map.contains(e) {
21            let old = map.remove(e).unwrap();
22            map.put(e, old.value() + 1);
23        } else {
24            map.put(e, 1);
25        }
26    }
27    println!("TreeMap character occurrence");
28    for e in map.iter() {
29        println!("{e:?}");
30    }
31
32    println!("\nTreeMap vowel occurrence");
33    for vowel in ['a', 'e', 'i', 'o', 'u', 'y'] {
34        eprintln!("{vowel}: {}", map.get(vowel).unwrap_or(&0));
35    }
36
37```
38
39```text
40TreeMap character occurrence
41('\n', 1)
42(' ', 24)
43(',', 1)
44('.', 1)
45('S', 1)
46('a', 12)
47('c', 4)
48('d', 2)
49('e', 14)
50('f', 3)
51('g', 2)
52('h', 5)
53('i', 5)
54('k', 1)
55('l', 5)
56('m', 2)
57('n', 6)
58('o', 7)
59('p', 4)
60('r', 8)
61('s', 2)
62('t', 7)
63('v', 2)
64('w', 1)
65('y', 2)
66
67TreeMap vowel occurrence
68a: 12
69e: 14
70i: 5
71o: 7
72u: 0
73y: 2
74```
75
76*/
77
78use crate::hierarchies::avl_tree::AVLTree;
79
80use std::borrow::Borrow;
81use std::cmp::Ordering;
82use std::fmt::Debug;
83
84/// The wrapper struct that allows TreeMap<K, V> to use AVLTree<T>.
85/// Because `T` is [Ord], Entry<K, V> must implement [Eq] and [PartialOrd],
86/// which themselves must implement [PartialEq].
87/// All traits use `key` for ordering.
88///
89/// See the [module-level documentation]() for more details.
90#[derive(Debug)]
91pub struct Entry<K, V> {
92    key: K,
93    value: V,
94}
95impl<K, V> Entry<K, V> {
96    pub fn key(&self) -> &K {
97        &self.key
98    }
99
100    pub fn value(&self) -> &V {
101        &self.value
102    }
103}
104impl<K: PartialEq, V> PartialEq for Entry<K, V> {
105    fn eq(&self, other: &Self) -> bool {
106        self.key == other.key
107    }
108}
109// Eq requires PartialEq
110impl<K: Eq, V> Eq for Entry<K, V> {}
111// PartialOrd requires PartialEq
112impl<K: PartialOrd, V> PartialOrd for Entry<K, V> {
113    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
114        self.key.partial_cmp(&other.key)
115    }
116}
117// Ord requires Eq + PartialOrd
118impl<K: Ord, V> Ord for Entry<K, V> {
119    fn cmp(&self, other: &Self) -> Ordering {
120        self.key.cmp(&other.key)
121    }
122}
123impl<K, V> Borrow<K> for Entry<K, V> {
124    fn borrow(&self) -> &K {
125        &self.key
126    }
127}
128
129///
130///
131/// See the [module-level documentation]() for more details.
132#[derive(Debug)]
133pub struct TreeMap<K, V> {
134    tree: AVLTree<Entry<K, V>>,
135    size: usize,
136}
137impl<K, V> Default for TreeMap<K, V>
138where
139    K: Default + Eq + Ord + PartialEq,
140{
141    fn default() -> Self {
142        Self::new()
143    }
144}
145impl<K, V> TreeMap<K, V>
146where
147    K: Default + Eq + Ord + PartialEq,
148{
149    /// Constructor
150    pub fn new() -> Self {
151        Self {
152            tree: AVLTree::<Entry<K, V>>::new(),
153            size: 0,
154        }
155    }
156
157    /// Returns the number of elements in the map.
158    pub fn size(&self) -> usize {
159        self.size
160    }
161
162    /// Returns `true` if the map contains an entry associated with the given key.
163    pub fn contains(&self, key: K) -> bool {
164        self.tree.contains(&key)
165    }
166
167    /// Returns the value associated with the key, if `Some`.
168    pub fn get(&self, key: K) -> Option<&V> {
169        if let Some(val) = self.tree.get_node(&key) {
170            return Some(&val.value);
171        }
172        None
173    }
174
175    /// Inserts the entry into the map. If the key already exists, removes
176    /// and returns the old entry and inserts a new one. This allows for
177    /// situations where keys are `==` without being _identical_.
178    pub fn put(&mut self, key: K, value: V) -> Option<Entry<K, V>> {
179        let new_entry = Entry { key, value };
180        let old_entry = self.tree.remove(&new_entry.key);
181        self.tree.insert(new_entry);
182        if old_entry.is_none() {
183            self.size += 1;
184        }
185        old_entry
186    }
187
188    /// Mutates
189    pub fn mut_val_or() {}
190
191    /// Removes and returns the entry associated with the key:value pair,
192    /// if it exists in the map.
193    pub fn remove(&mut self, key: K) -> Option<Entry<K, V>> {
194        if self.tree.contains(&key) {
195            self.size -= 1;
196            return self.tree.remove(&key);
197        }
198        None
199    }
200
201    /// Returns an iterator over borrowed values. The resulting values
202    /// appear in sorted order.
203    ///
204    /// Example use:
205    /// ```rust
206    /// use dsa_rust::associative::probing_hash_table::HashMap;
207    /// let mut count: HashMap<char, u8> = HashMap::new();
208    /// let mut v = Vec::new();
209    /// for e in count.iter() {
210    ///     v.push(*e.0);
211    /// }
212    /// ```
213    pub fn iter(&self) -> Iter<'_, K, V> {
214        Iter {
215            iter: self.tree.iter(),
216        }
217    }
218}
219
220pub struct Iter<'a, K, V> {
221    //iter: std::slice::Iter<'a, Option<Entry<K, V>>>,
222    iter: crate::hierarchies::avl_tree::InOrderIter<
223        'a,
224        crate::associative::avl_tree_map::Entry<K, V>,
225    >,
226}
227impl<'a, K, V> Iterator for Iter<'a, K, V>
228where
229    K: Debug + PartialEq,
230    V: PartialEq,
231{
232    type Item = (&'a K, &'a V);
233
234    fn next(&mut self) -> Option<Self::Item> {
235        self.iter.next().map(|entry| (&entry.key, &entry.value))
236    }
237}
238
239#[test]
240// Generic type test
241fn avl_tree_map_test() {
242    //Creates a new hash map
243    let mut map = TreeMap::<&str, u8>::new();
244
245    assert_eq!(map.size(), 0);
246
247    // Illustrates that put() and get() work
248    map.put("Peter", 40);
249    assert_eq!(map.size(), 1);
250
251    // Illustrates that the map grows correctly
252    map.put("Brain", 39); // Grows the map
253    map.put("Remus", 22);
254    map.put("Bobson", 36); // Grows the map
255    map.put("Dingus", 18);
256    map.put("Dangus", 27); // Grows the map
257    assert_eq!(map.size(), 6);
258
259    // Underlying tree arena check
260    eprintln!("Initial state");
261    assert_eq!(map.tree.arena.len(), 6);
262    for e in map.tree.arena.iter() {
263        eprintln!("{e:?}")
264    }
265
266    // Illustrates that contains() works as intended
267    assert!(map.contains("Dingus"));
268
269    // Illustrates that put() returns old values and
270    // overwrites existing values upon collision...
271    let old = map.put("Peter", 41).unwrap();
272    assert_eq!(old.value, 40_u8);
273    let new_val = map.get("Peter").unwrap();
274    assert_eq!(*new_val, 41);
275    assert_eq!(map.size(), 6);
276
277    // Underlying tree arena check
278    eprintln!("After replacement");
279    assert_eq!(map.tree.arena.len(), 7);
280    for e in map.tree.arena.iter() {
281        eprintln!("{e:?}")
282    }
283
284    // Illustrates that removes entries by key and returns the value
285    assert!(map.contains("Dangus"));
286    let removed = map.remove("Dangus").unwrap();
287    assert_eq!(map.size(), 5);
288
289    // Underlying tree arena check
290    eprintln!("After removal");
291    assert_eq!(map.tree.arena.len(), 7);
292    for e in map.tree.arena.iter() {
293        eprintln!("{e:?}")
294    }
295
296    //assert_eq!(removed.key(), &"Dangus");
297    //assert_eq!(removed.value(), &27);
298    assert_eq!(removed.key, "Dangus");
299    assert_eq!(removed.value, 27);
300    assert!(!map.contains("Dangus"));
301
302    eprintln!("{map:#?}");
303
304    //panic!("MANUAL TEST FAILURE");
305}
306//
307//#[test]
308// //Tests the custom update value function
309//fn mut_val_test() {
310//    //Creates a new hash map
311//    let mut count = HashMap::<char, u8>::new();
312//    let phrase: &str = "Hello, sickos";
313//
314//    // Seeds the map with just the characters and a default value
315//    for char in phrase.chars() {
316//        count.put(char, 0);
317//    }
318//
319//    eprintln!("\nInitial state:");
320//    count.contents();
321//
322//    // Iterates through the map again, updating each value based on its occurence
323//    // NOTE: Can also be used as initial mapping operation with the same code,
324//    // but was split here for illustrative purposes
325//    for char in phrase.chars() {
326//        count.mut_val_or(char, |x| *x += 1, 1);
327//    }
328//
329//    // Pretty-prints the contents of the map
330//    eprintln!("\nModified:");
331//    count.contents();
332//
333//    // Uncomment to trigger debug print
334//    //assert!(count.is_empty());
335//}
336//
337#[test]
338// Tests that the structure is iterable
339fn iter_test() {
340    //Creates a new hash map of the frequence letters in the given phrase
341    let mut map = TreeMap::<usize, char>::new();
342    for (index, char) in "acbjfed".chars().enumerate() {
343        map.put(index, char); // index is key, char is value
344    }
345
346    // Indicates that the map is indeed sorted
347    eprintln!("\nSorted map:");
348    for e in map.tree.iter() {
349        eprintln!("{e:?}")
350    }
351
352    // Prints only the middle values based on key range
353    // which should be "b, j, f, e"
354    eprintln!("\nPrint values for indexes 2..=5:");
355    for e in 2..=5 {
356        let val = map.get(e).unwrap();
357        eprintln!("{val:?}");
358    }
359
360    //let text = "Not the most elegant text, but it sure
361    //    does the trick when you need it. I could go on and on and on,
362    //but instead Id rather just let the text explain itself in order to Illustrate
363    //    what this test is all about. Then again Im not sure I could do this without
364    //    just a little rambling, amirite? You're the kind of person that
365    //    gets it, I think.";
366
367    let text = "and the final paragraph clearly came from the heart, 
368    or whatever cool yet sensitive organ Sadie kept in place of one.";
369
370    // Establishes parity with the std BTreeMap
371    //let mut map = std::collections::BTreeMap::<char, usize>::new();
372    //for e in text.chars() {
373    //    if map.contains_key(&e) {
374    //        let old = map.remove(&e).unwrap();
375    //        map.insert(e, old + 1);
376    //    } else {
377    //        map.insert(e, 1);
378    //    }
379    //}
380    //eprintln!("\nBTreeMap character occurrence");
381    //for e in map.iter() {
382    //    eprintln!("{e:?}");
383    //}
384
385    // Second attempt with custom TreeMap
386    let mut map = TreeMap::<char, usize>::new();
387    for e in text.chars() {
388        if map.contains(e) {
389            let old = map.remove(e).unwrap();
390            map.put(e, old.value + 1);
391        } else {
392            map.put(e, 1);
393        }
394    }
395    eprintln!("\nTreeMap character occurrence");
396
397    //for e in map.tree.iter() {
398    //    eprintln!("({:?}, {})", e.key, e.value);
399    //}
400    for e in map.iter() {
401        eprintln!("{e:?}");
402    }
403
404    eprintln!("\nTreeMap vowel occurrence");
405    for vowel in ['a', 'e', 'i', 'o', 'u', 'y'] {
406        eprintln!("{vowel}: {}", map.get(vowel).unwrap_or(&0));
407    }
408    eprintln!("\nTreeMap occurrence of characters in my name");
409    for vowel in ['p', 'e', 't', 'r'] {
410        eprintln!("{vowel}: {}", map.get(vowel).unwrap_or(&0));
411    }
412
413    // Uncomment to trigger debug print
414    //panic!("MANUAL TEST FAILURE");
415}