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.push(Node::new(self.arena.len(), key, parent));
284 } else {
285 // The list is empty, insert a new root
286 self.arena.push(Node::new(0, key, None));
287 }
288 }
289
290 fn is_leaf(&self, index: usize) -> Result<bool, &str> {
291 match self.get_node(index) {
292 Some(val) => {
293 if val.get_children() == (None, None) {
294 Ok(true)
295 } else {
296 Ok(false)
297 }
298 }
299 None => Err("Invalid index"),
300 }
301 }
302
303 pub fn remove(&mut self, key: T) -> Option<T> {
304 // Exists with None if the key is not in the tree
305 if let Some(index) = self.find_index(&key) {
306 //let index = self.find_index(&key);
307
308 // Check if the key is actually in the tree by
309 // checking if the index represents the key or its parent
310 //
311 // The key is in the index
312 if self.arena[index].value.as_ref().unwrap() == &key {
313 // Case 1) The node to delete has two children
314 if self.arena[index].left.is_some() && self.arena[index].right.is_some() {
315 // TODO: Implement
316
317 // Get the node, take its value
318 self.arena[index].value.take()
319
320 // Case 2) The node has only one child
321 } else if self.arena[index].left.is_some() || self.arena[index].right.is_some() {
322 // Update the parent's child pointer to the removed node's child
323 if self.arena[index].parent.is_some() {
324 // Determine whether the removed is the right or left child of its parent
325 let parent = self.arena[index].parent.unwrap();
326
327 // The removed node is the right child of its parent
328 if self.arena[parent].right.as_ref().unwrap() == &index {
329 // The removed node only has a left child
330 if self.arena[index].left.is_some() {
331 // Update the parent's right child pointer to the removed node's left
332 // child
333 self.arena[parent].right = Some(self.arena[index].left?);
334 // Update the removed node's left child to point to the removed node's
335 // parent
336 let child = self.arena[index].left.unwrap();
337 self.arena[child].parent = Some(parent);
338 // The removed node only has a right child
339 } else {
340 // Update the parent's right child pointer to the removed node's right
341 // child
342 self.arena[parent].right = Some(self.arena[index].right?);
343 // Update the removed node's right child to point to the removed node's
344 // parent
345 let child = self.arena[index].right.unwrap();
346 self.arena[child].parent = Some(parent);
347 }
348 }
349 // The removed node is the left child
350 else {
351 // The removed node only has a left child
352 if self.arena[index].left.is_some() {
353 // Update the parent's left child pointer to the removed node's left
354 // child
355 self.arena[parent].left = Some(self.arena[index].left?);
356 // The removed node only has a right child
357 } else {
358 // Update the parent's left child pointer to the removed node's right
359 // child
360 self.arena[parent].left = Some(self.arena[index].right?);
361 }
362 }
363 }
364
365 // Get the node, take/return its value
366 self.arena[index].value.take()
367
368 // Case 3) The node has no children
369 } else {
370 None
371 }
372
373 // update the parent's child pointer
374 // update the replacement node's parent pointer
375 }
376 // The key is not in the tree; no op
377 else {
378 None
379 }
380 } else {
381 None
382 }
383 }
384
385 /// Produces a "snapshot" iterator over immutable references to the
386 /// tree in its current state.
387 pub fn iter(&self) -> InOrderIter<'_, T> {
388 InOrderIter::new(&self.arena[self.root.expect("IDK man")])
389 }
390}
391
392pub struct InOrderIter<'a, T> {
393 stack: Vec<&'a Node<T>>,
394 current: Option<&'a Node<T>>,
395}
396impl<'a, T> InOrderIter<'a, T> {
397 fn new(root: &'a Node<T>) -> Self {
398 Self {
399 stack: Vec::new(),
400 current: Some(root),
401 }
402 }
403}
404//impl<'a, T> Iterator for InOrderIter<'a, T> {
405// type Item = &'a T;
406//
407// fn next(&mut self) -> Option<Self::Item> {
408// while let Some(node) = self.current {
409// self.stack.push(node);
410// self.current = item.arena[node.left];
411// }
412//
413// self.stack.pop().map(|node| {
414// self.current = node.right.as_deref();
415// &node.value
416// })
417// }
418//}
419
420//#[test]
421//fn basic_bst() {
422// let mut bst: BinSearchTree<u8> = BinSearchTree::new();
423//
424// // Produces a BST
425// let v = [31, 13, 23, 39, 41, 43, 8, 17, 19];
426// for e in v.iter() {
427// bst.insert(*e);
428// }
429//
430// eprintln!("{bst:#?}");
431// assert_eq!(bst.arena[bst.root.expect("No root")].value, Some(31));
432// let root_node = &bst.arena[bst.root.expect("nah, brah")];
433// assert_eq!(bst.arena[root_node.left.unwrap()].value, Some(13));
434// assert_eq!(bst.arena[root_node.right.unwrap()].value, Some(39));
435//}