dsa_rust/hierarchies/arena_bst.rs
1/*! A safe, arena-based (indexed) binary search tree (BST)
2
3# About
4A binary search tree is a binary tree where the value of each node's child is less than or greater than its parent. Left children are less than their parents, and right children are greater than their parents.
5
6Due to common usage when implementing sorted map and set structures, this implementation does not accept duplicate entries.
7
8# Design
9The design uses a flat, [Vec]-backed structure with iterative navigation. This arena-allocated design provides robust, performant operations while keeping runtime checks to a minimum. The goal of this approach is to avoid unnecessary overhead with recursive operations and extra heap allocations, making it suitable for low-spec environments.
10
11# Example
12*/
13
14#![allow(dead_code)] // While we cook
15
16use std::cmp::Ordering;
17
18// Experiment in custom sum types
19enum Position {
20 // Key exists
21 Found(usize),
22 // Insertion information for new key
23 Parent(usize),
24}
25
26enum Side {
27 Left,
28 Right,
29}
30
31#[derive(Debug)]
32struct Node<T> {
33 index: usize, // Strictly necessary?
34 value: Option<T>, // Wrapping the value allows us quick take() operations
35 parent: Option<usize>,
36 left: Option<usize>, // Explicit and simple
37 right: Option<usize>,
38 height: usize,
39}
40impl<T> Node<T> {
41 // Creates a new node with its current index, a value, and its parent (if Some).
42 // Guarantees that all nodes have a value.
43 fn new(index: usize, value: T, parent: Option<usize>) -> Self {
44 Node {
45 index,
46 value: Some(value),
47 parent,
48 left: None,
49 right: None,
50 height: 0,
51 }
52 }
53
54 // Gets the parent index of the node, if Some
55 fn get_parent(&self) -> Option<usize> {
56 self.parent
57 }
58
59 /// Returns a tuple of the node's children
60 /// 0 == left
61 /// 1 == right
62 fn get_children(&self) -> (Option<usize>, Option<usize>) {
63 (self.left, self.right)
64 }
65
66 // Returns a reference to the node's value, if Some
67 fn get_value(&self) -> Option<&T> {
68 self.value.as_ref()
69 //match &self.value {
70 // Some(val) => Some(val),
71 // None => None
72 //}
73 }
74}
75
76#[derive(Debug)]
77pub struct BinSearchTree<T> {
78 arena: Vec<Node<T>>,
79 root: Option<usize>, // Wont always be 0, and wont always be Some!
80}
81// Im just here to make Clippy happy
82impl<T> Default for BinSearchTree<T>
83where
84 T: Ord,
85{
86 fn default() -> Self {
87 Self::new()
88 }
89}
90impl<T> BinSearchTree<T>
91where
92 T: Ord,
93{
94 /// Creates a new, empty binary search tree.
95 pub fn new() -> Self {
96 BinSearchTree {
97 arena: Vec::new(),
98 root: None,
99 }
100 }
101
102 /// Creates a new, empty binary search tree with a given (growable) initial capacity.
103 pub fn new_with_capacity(size: usize) -> Self {
104 BinSearchTree {
105 arena: Vec::with_capacity(size),
106 root: Some(0),
107 }
108 }
109
110 /// The index of a found key or the root of
111 /// the sub-tree for its insertion point, if Some.
112 /// Returns None for an empty/corrupted tree.
113 /// Returns Option because the structure cannot guarantee initialized trees.
114 ///
115 /// This naive implementation can be used independently or within
116 /// a map that does _not_ support duplicates as it does not
117 /// discriminate between found and not found.
118 fn find_index(&self, key: &T) -> Option<usize>
119 where
120 T: Ord,
121 {
122 let mut current = self.root?; // Return None if empty
123 while let Some(node) = self.arena.get(current) {
124 let value = node.get_value()?; // Return None if corrupted
125 match value.cmp(key) {
126 Ordering::Less => {
127 if let Some(right) = node.right {
128 current = right;
129 } else {
130 break;
131 } // return insert position
132 }
133 Ordering::Greater => {
134 if let Some(left) = node.left {
135 current = left;
136 } else {
137 break;
138 } // return insert position
139 }
140 Ordering::Equal => break, // key found
141 }
142 }
143 Some(current)
144 }
145
146 /// Returns a `Position` that contains the index of the key if `Found`,
147 /// or the root of the sub-tree for its insertion point as `Parent`,
148 /// which could be 0 for an empty tree.
149 /// (All trees are guaranteed to be initialized)
150 fn find_index_enum(&self, _key: &T) -> Position {
151 if let Some(mut _index) = self.root {
152 return Position::Found(0);
153 }
154
155 // Search iteratively from the root to find a match or insertion parent
156 //while let Some(index) = self.arena.get(self.root.expect("Uh oh")) {
157 // // SAFETY: Every node created with Node::new() is guaranteed to have a value
158 // match index.value.as_ref().unwrap().cmp(key) {
159 // Ordering::Less => {
160 // if let Some(right) = index.right {
161 // index = right;
162 // } else {
163 // break;
164 // }
165 // }
166 // Ordering::Greater => {
167 // if let Some(left) = index.left {
168 // index = left;
169 // } else {
170 // break;
171 // }
172 // }
173 // Ordering::Equal => break,
174 // }
175 //}
176 //
177 //index
178 Position::Found(0)
179 }
180
181 /// Returns a tuple that contains information for whether the key exists
182 /// in the tree, and if so its index, if not, the insertion point (parent index)
183 /// Examples:
184 /// - The key is in the tree at index 23: (Some(23), None)
185 /// - The key is not in the index, but its parent should be index 7 (None, Some(7))
186 ///
187 /// Use the following pseudocode for contains():
188 /// ```text
189 /// match tree.find_index_exact(key).0 {
190 /// Some(val) => true,
191 /// None => false,
192 /// }
193 /// ```
194 ///
195 /// Use the following pseudocode to locate the insertion point:
196 /// ```text
197 /// if let Some(parent) = tree.find_index_exact(key).1 { ... }
198 /// ```
199 fn find_index_exact(&self, key: &T) -> (Option<usize>, Option<usize>) {
200 if let Some(mut index) = self.root {
201 //let mut index = self.root;
202 let mut tuple = (None, None);
203
204 while let Some(node) = self.arena.get(index) {
205 // SAFETY: Every node created with Node::new() is guaranteed to have a value
206 match node.value.as_ref().unwrap().cmp(key) {
207 Ordering::Less => {
208 // Go right, continue search
209 if let Some(right) = node.right {
210 index = right;
211 } else {
212 // The key should be the right child of index
213 tuple = (None, Some(index));
214 break;
215 }
216 }
217 Ordering::Greater => {
218 // Go left, continue search
219 if let Some(left) = node.left {
220 index = left;
221 } else {
222 // The key should be the left child of index
223 tuple = (None, Some(index));
224 break;
225 }
226 }
227 // The key exists at index
228 Ordering::Equal => {
229 tuple = (Some(index), None);
230 break;
231 }
232 }
233 }
234
235 tuple
236 } else {
237 // The tree is empty
238 (None, None)
239 }
240 }
241
242 fn get_node(&self, index: usize) -> Option<&Node<T>> {
243 if index < self.arena.len() {
244 Some(&self.arena[index])
245 } else {
246 None
247 }
248 }
249
250 /// Inserts the given key into the tree. New insertions in a simple
251 /// BST are always leafs. This implementation does not guarantee uniqueness.
252 pub fn insert(&mut self, key: T) {
253 if !self.arena.is_empty() {
254 // Find the (presumptive) parent index
255 let parent = self.find_index(&key);
256
257 // If the parent == key, no op, otherwise its indeed the parent
258 //match &key.cmp(self.arena[parent_index].value.as_ref().unwrap()) {
259 match &key.cmp(
260 self.get_node(parent.expect(""))
261 .unwrap()
262 .get_value()
263 .as_ref()
264 .unwrap(),
265 ) {
266 // The key already exists, no op
267 Ordering::Equal => {}
268 // The key is less than the value at the index, go left
269 Ordering::Less => {
270 // New node is a left child of parent
271 self.arena[parent.expect("")].left = Some(self.arena.len())
272 //self.get_node(parent).unwrap().get_children().0 = Some(self.arena.len())
273 }
274 // The key is greater than the value at the index, go right
275 Ordering::Greater => {
276 // parent is true!
277 // New node is a right child of parent
278 self.arena[parent.expect("")].right = Some(self.arena.len())
279 }
280 }
281
282 // Create & insert the node
283 self.arena
284 .push(Node::new(self.arena.len(), key, parent));
285 } else {
286 // The list is empty, insert a new root
287 self.arena.push(Node::new(0, key, None));
288 }
289 }
290
291 fn is_leaf(&self, index: usize) -> Result<bool, &str> {
292 match self.get_node(index) {
293 Some(val) => {
294 if val.get_children() == (None, None) {
295 Ok(true)
296 } else {
297 Ok(false)
298 }
299 }
300 None => Err("Invalid index"),
301 }
302 }
303
304 pub fn remove(&mut self, key: T) -> Option<T> {
305 // Exists with None if the key is not in the tree
306 if let Some(index) = self.find_index(&key) {
307 //let index = self.find_index(&key);
308
309 // Check if the key is actually in the tree by
310 // checking if the index represents the key or its parent
311 //
312 // The key is in the index
313 if self.arena[index].value.as_ref().unwrap() == &key {
314 // Case 1) The node to delete has two children
315 if self.arena[index].left.is_some() && self.arena[index].right.is_some() {
316 // TODO: Implement
317
318 // Get the node, take its value
319 self.arena[index].value.take()
320
321 // Case 2) The node has only one child
322 } else if self.arena[index].left.is_some() || self.arena[index].right.is_some() {
323 // Update the parent's child pointer to the removed node's child
324 if self.arena[index].parent.is_some() {
325 // Determine whether the removed is the right or left child of its parent
326 let parent = self.arena[index].parent.unwrap();
327
328 // The removed node is the right child of its parent
329 if self.arena[parent].right.as_ref().unwrap() == &index {
330 // The removed node only has a left child
331 if self.arena[index].left.is_some() {
332 // Update the parent's right child pointer to the removed node's left
333 // child
334 self.arena[parent].right = Some(self.arena[index].left?);
335 // Update the removed node's left child to point to the removed node's
336 // parent
337 let child = self.arena[index].left.unwrap();
338 self.arena[child].parent = Some(parent);
339 // The removed node only has a right child
340 } else {
341 // Update the parent's right child pointer to the removed node's right
342 // child
343 self.arena[parent].right = Some(self.arena[index].right?);
344 // Update the removed node's right child to point to the removed node's
345 // parent
346 let child = self.arena[index].right.unwrap();
347 self.arena[child].parent = Some(parent);
348 }
349 }
350 // The removed node is the left child
351 else {
352 // The removed node only has a left child
353 if self.arena[index].left.is_some() {
354 // Update the parent's left child pointer to the removed node's left
355 // child
356 self.arena[parent].left = Some(self.arena[index].left?);
357 // The removed node only has a right child
358 } else {
359 // Update the parent's left child pointer to the removed node's right
360 // child
361 self.arena[parent].left = Some(self.arena[index].right?);
362 }
363 }
364 }
365
366 // Get the node, take/return its value
367 self.arena[index].value.take()
368
369 // Case 3) The node has no children
370 } else {
371 None
372 }
373
374 // update the parent's child pointer
375 // update the replacement node's parent pointer
376 }
377 // The key is not in the tree; no op
378 else {
379 None
380 }
381 } else {
382 None
383 }
384 }
385
386 /// Produces a "snapshot" iterator over immutable references to the
387 /// tree in its current state.
388 pub fn iter(&self) -> InOrderIter<'_, T> {
389 InOrderIter::new(&self.arena[self.root.expect("IDK man")])
390 }
391}
392
393pub struct InOrderIter<'a, T> {
394 stack: Vec<&'a Node<T>>,
395 current: Option<&'a Node<T>>,
396}
397impl<'a, T> InOrderIter<'a, T> {
398 fn new(root: &'a Node<T>) -> Self {
399 Self {
400 stack: Vec::new(),
401 current: Some(root),
402 }
403 }
404}
405//impl<'a, T> Iterator for InOrderIter<'a, T> {
406// type Item = &'a T;
407//
408// fn next(&mut self) -> Option<Self::Item> {
409// while let Some(node) = self.current {
410// self.stack.push(node);
411// self.current = item.arena[node.left];
412// }
413//
414// self.stack.pop().map(|node| {
415// self.current = node.right.as_deref();
416// &node.value
417// })
418// }
419//}
420
421//#[test]
422//fn basic_bst() {
423// let mut bst: BinSearchTree<u8> = BinSearchTree::new();
424//
425// // Produces a BST
426// let v = [31, 13, 23, 39, 41, 43, 8, 17, 19];
427// for e in v.iter() {
428// bst.insert(*e);
429// }
430//
431// eprintln!("{bst:#?}");
432// assert_eq!(bst.arena[bst.root.expect("No root")].value, Some(31));
433// let root_node = &bst.arena[bst.root.expect("nah, brah")];
434// assert_eq!(bst.arena[root_node.left.unwrap()].value, Some(13));
435// assert_eq!(bst.arena[root_node.right.unwrap()].value, Some(39));
436//}