├── .gitignore ├── Cargo.toml ├── LICENSE ├── README.md ├── src ├── array_list.rs ├── binary_search_tree.rs ├── doubly_linked_list.rs ├── lib.rs ├── linked_list.rs ├── priority_queue.rs ├── queue.rs ├── ring_buffer.rs ├── stack.rs └── vec.rs └── tests └── thread_tests.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | 17 | # Added by cargo 18 | 19 | /target 20 | /Cargo.lock 21 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-dsa" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Michael J Erwin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rust-dsa 2 | Data Structures & Algorithms implemented in Rust 3 | -------------------------------------------------------------------------------- /src/array_list.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | /* 3 | 4 | * Wrapper that uses arrays under the hood 5 | * push/pop/access has O(1) 6 | * enqueue/deque has O(N) 7 | * constructor specifies initial size 8 | 9 | 10 | TypeScript example: 11 | export default class ArrayList { 12 | public length: number; 13 | constructor() {} 14 | prepend(item: T): void {} 15 | insertAt(item: T, idx: number): void {} 16 | append(item: T): void {} 17 | remove(item: T): T | undefined {} 18 | get(idx: number): T | undefined {} 19 | removeAt(idx: number): T | undefined {} 20 | } 21 | */ 22 | use std::fmt::Debug; 23 | // My Fake Array, we're pretending all we can do is get length and not grow this 24 | type Array = Vec; 25 | 26 | #[derive(Debug)] 27 | struct ArrayList { 28 | pub length: usize, 29 | inner: Array, 30 | } 31 | 32 | impl ArrayList { 33 | pub fn new() -> ArrayList { 34 | ArrayList { 35 | length: 0, 36 | inner: vec![T::default(); 5], 37 | } 38 | } 39 | 40 | fn grow_inner(&mut self) { 41 | let prev = &self.inner; 42 | let mut new = vec![T::default(); prev.len() * 2]; 43 | for i in 0..prev.len() { 44 | new[i] = prev[i].clone(); 45 | } 46 | self.inner = new; 47 | } 48 | 49 | pub fn append(&mut self, item: T) { 50 | println!("appending {item:?} to {self:?}"); 51 | if self.inner.len() == self.length { 52 | self.grow_inner(); 53 | } 54 | self.inner[self.length] = item; 55 | self.length = self.length + 1; 56 | } 57 | 58 | pub fn pop(&mut self) -> Option { 59 | if self.length == 0 { 60 | return None; 61 | } 62 | let tail = self.length - 1; 63 | let item = self.inner[tail].clone(); 64 | println!("removing {item:?} from {self:?}"); 65 | self.inner[tail] = T::default(); 66 | self.length = tail; 67 | Some(item) 68 | } 69 | 70 | pub fn remove_at(&mut self, index: usize) -> Option { 71 | if index < self.length { 72 | let item = self.inner[index].clone(); 73 | for i in index..self.length { 74 | self.inner[i] = self.inner[i + 1].clone(); 75 | } 76 | self.length = self.length - 1; 77 | Some(item) 78 | } else { 79 | None 80 | } 81 | } 82 | 83 | pub fn remove(&mut self, item: &T) -> Option { 84 | for i in 0..self.length { 85 | if &self.inner[i] == item { 86 | return self.remove_at(i); 87 | } 88 | } 89 | None 90 | } 91 | 92 | pub fn get(&self, i: usize) -> Option<&T> { 93 | if i < self.length { 94 | Some(&self.inner[i]) 95 | } else { 96 | None 97 | } 98 | } 99 | 100 | pub fn insert_at(&mut self, index: usize, item: T) { 101 | println!("inserting {item:?} at {index:?} into {self:?}"); 102 | if self.inner.len() == self.length { 103 | self.grow_inner(); 104 | } 105 | for i in ((index + 1)..=self.length).rev() { 106 | self.inner[i] = self.inner[i - 1].clone(); 107 | } 108 | self.inner[index] = item; 109 | self.length = self.length + 1; 110 | } 111 | 112 | pub fn prepend(&mut self, item: T) { 113 | println!("prepending {item:?} to {self:?}"); 114 | self.insert_at(0, item); 115 | } 116 | } 117 | 118 | #[cfg(test)] 119 | mod tests { 120 | use super::*; 121 | 122 | #[test] 123 | fn array_list_works() { 124 | let mut l = ArrayList::::new(); 125 | assert_eq!(None, l.pop()); 126 | l.append(1); 127 | l.append(2); 128 | l.append(3); 129 | l.append(4); 130 | l.append(5); 131 | l.append(-1); 132 | assert_eq!(Some(&5), l.get(4)); 133 | let item = l.pop(); 134 | assert_eq!(Some(-1), item); 135 | assert_eq!(5, l.length); 136 | assert_eq!(Some(&3), l.get(2)); 137 | assert_eq!(None, l.get(l.length)); 138 | l.prepend(1000); 139 | assert_eq!(Some(&1000), l.get(0)); 140 | assert_eq!(Some(&1), l.get(1)); 141 | assert_eq!(Some(&2), l.get(2)); 142 | assert_eq!(Some(&5), l.get(l.length - 1)); 143 | assert_eq!(6, l.length); 144 | l.insert_at(1, 2000); 145 | assert_eq!(Some(&2000), l.get(1)); 146 | assert_eq!(Some(2000), l.remove_at(1)); 147 | assert_eq!(6, l.length); 148 | assert_eq!(Some(&5), l.get(l.length - 1)); 149 | assert_eq!(Some(3), l.remove(&3)); 150 | assert_eq!(None, l.remove(&500)); 151 | assert_eq!(5, l.length); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/binary_search_tree.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::fmt::Debug; 3 | 4 | /** 5 | * Binary Search Tree 6 | * sorted 7 | * Node.left.value < Node.value 8 | * Node.right.value >= Node.value 9 | * search, insertion & removal: O(log N) 10 | * Vec: input & output, impl From>, Into>, 11 | */ 12 | #[derive(Clone)] 13 | pub struct BinarySearchTree { 14 | root: Option>>, 15 | } 16 | 17 | #[derive(Clone, Debug)] 18 | struct Node { 19 | value: T, 20 | left: Option>>, 21 | right: Option>>, 22 | } 23 | 24 | /* 25 | Debug: 26 | R 27 | --L 28 | ----LL 29 | ----LR 30 | --R 31 | ----RL 32 | ----RR 33 | */ 34 | impl Debug for BinarySearchTree { 35 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 36 | // keep track of what level we're at 37 | // print `--` * level 38 | let mut level = 0; 39 | // need to keep track of level within traverse so general traverse doesn't work 40 | self.preorder_traverse(&mut |v| { 41 | let r = write!(f, "\n{:->level$}{v:?}", ""); 42 | level += 1; 43 | r 44 | }); 45 | Ok(()) 46 | } 47 | } 48 | 49 | impl Node { 50 | fn insert_child(&mut self, node: Node) { 51 | let branch = if node.value < self.value { 52 | &mut self.left 53 | } else { 54 | &mut self.right 55 | }; 56 | if branch.is_none() { 57 | branch.replace(Box::new(node)); 58 | } else { 59 | branch.as_mut().unwrap().insert_child(node); 60 | } 61 | } 62 | 63 | /// Assumes that self.list.is_some() 64 | fn replace_left_with_left_child(&mut self) -> Option> { 65 | if self.left.as_mut().unwrap().left.is_some() { 66 | let l = self.left.as_mut().unwrap().left.take().unwrap(); 67 | self.left.replace(l) 68 | } else { 69 | self.left.take() 70 | } 71 | } 72 | 73 | /// Assumes that self.right.is_some() 74 | fn replace_right_with_child(&mut self) -> Option> { 75 | if let Some(left_child) = self.right.as_mut().unwrap().left.take() { 76 | self.right.replace(left_child) 77 | } else if let Some(right_child) = self.right.as_mut().unwrap().right.take() { 78 | self.right.replace(right_child) 79 | } else { 80 | self.right.take() 81 | } 82 | } 83 | 84 | /// bad name, not what it does really 85 | fn recur_right(&mut self) -> Option> { 86 | if let Some(n) = &mut self.right { 87 | if n.right.is_some() { 88 | n.recur_right() 89 | } else { 90 | self.replace_right_with_child() 91 | } 92 | } else { 93 | None 94 | } 95 | } 96 | 97 | fn leftmost<'a>(&'a self, stack: &mut Vec<&'a Node>) -> &Self { 98 | if let Some(n) = &self.left { 99 | stack.push(self); 100 | n.leftmost(stack) 101 | } else { 102 | self 103 | } 104 | } 105 | 106 | fn swap_node(&mut self) -> Option<&mut Self> { 107 | let swap_node = if let Some(left) = &mut self.left { 108 | let rightmost = left.recur_right(); 109 | if rightmost.is_some() { 110 | rightmost 111 | } else { 112 | self.replace_left_with_left_child() 113 | } 114 | } else if self.right.is_some() { 115 | self.replace_right_with_child() 116 | } else { 117 | None 118 | }; 119 | 120 | if let Some(swap_n) = swap_node { 121 | self.value = swap_n.value; 122 | Some(self) 123 | } else { 124 | None 125 | } 126 | } 127 | 128 | // this doesn't work for deleting root node 129 | fn delete_from(&mut self, value: T) -> Option { 130 | if value < self.value { 131 | match self.left.as_mut() { 132 | None => None, 133 | Some(n) if value == n.value => { 134 | if n.swap_node().is_none() { 135 | self.left = None; 136 | } 137 | Some(value) 138 | }, 139 | Some(n) => n.delete_from(value), 140 | } 141 | } else { 142 | match self.right.as_mut() { 143 | None => None, 144 | Some(n) if value == n.value => { 145 | if n.swap_node().is_none() { 146 | self.right = None; 147 | } 148 | Some(value) 149 | } 150 | Some(n) => n.delete_from(value), 151 | } 152 | } 153 | } 154 | 155 | fn search(&self, value: T) -> Option<&Self> { 156 | if value == self.value { 157 | Some(self) 158 | } else if value < self.value { 159 | self.left.as_ref().and_then(|n| n.search(value)) 160 | } else { 161 | self.right.as_ref().and_then(|n| n.search(value)) 162 | } 163 | } 164 | 165 | /// In order traversal applying f to self.value, consuming self 166 | fn traverse(mut self, f: &mut F) 167 | where F: FnMut(T), 168 | { 169 | if let Some(l) = self.left.take() { 170 | l.traverse(f); 171 | } 172 | let right = self.right.take(); 173 | f(self.value); 174 | 175 | if let Some(r) = right { 176 | r.traverse(f); 177 | } 178 | } 179 | 180 | fn preorder_traverse(&self, f: &mut F) 181 | where F: FnMut(&T) -> K, 182 | { 183 | f(&self.value); 184 | 185 | if let Some(l) = self.left.as_ref() { 186 | l.preorder_traverse(f); 187 | } 188 | 189 | if let Some(r) = self.right.as_ref() { 190 | r.preorder_traverse(f); 191 | } 192 | } 193 | } 194 | 195 | impl BinarySearchTree { 196 | pub fn new() -> Self { 197 | BinarySearchTree { root: None } 198 | } 199 | 200 | pub fn insert(&mut self, value: T) { 201 | let node = Node { 202 | value, 203 | left: None, 204 | right: None, 205 | }; 206 | 207 | if self.root.is_none() { 208 | self.root = Some(Box::new(node)); 209 | } else { 210 | self.root.as_mut().unwrap().insert_child(node); 211 | } 212 | } 213 | 214 | pub fn search(&self, value: T) -> bool { 215 | self.root.as_ref().and_then(|n| n.search(value)).is_some() 216 | } 217 | 218 | // if deleted node doesn't have children, remove from parent and return value 219 | // if it has children, take the node.left.right(most) node and replace it 220 | pub fn delete(&mut self, value: T) -> Option { 221 | match self.root.as_mut() { 222 | None => None, 223 | Some(n) if value == n.value => { 224 | if n.swap_node().is_none() { 225 | self.root = None; 226 | } 227 | Some(value) 228 | }, 229 | Some(n) => n.delete_from(value), 230 | } 231 | } 232 | 233 | /// In order traversal applying `f` to each `T` consuming `self` 234 | fn traverse(mut self, f: &mut F) 235 | where F: FnMut(T), 236 | { 237 | if let Some(n) = self.root.take() { 238 | n.traverse(f); 239 | } 240 | } 241 | 242 | fn preorder_traverse(&self, f: &mut F) 243 | where F: FnMut(&T) -> K, 244 | { 245 | if let Some(n) = self.root.as_ref() { 246 | n.preorder_traverse(f); 247 | } 248 | } 249 | 250 | /* This is O(log N) because we're calculating the first node to produce in the `iter` method 251 | * If we wanted to make this more efficient, we could add `root` and `initial` fields 252 | * to our BSTIterator and caclulate the first `current` in the first call of `next` 253 | */ 254 | pub fn iter<'a>(&'a self) -> BSTIterator<'a, T> { 255 | let mut stack = Vec::new(); 256 | let current = self.root.as_ref().map(|n| n.leftmost(&mut stack)); 257 | BSTIterator { 258 | stack, 259 | current, 260 | } 261 | } 262 | } 263 | 264 | pub struct BSTIterator<'a, T> { 265 | stack: Vec<&'a Node>, 266 | current: Option<&'a Node>, 267 | } 268 | 269 | impl<'a, T: PartialOrd> Iterator for BSTIterator<'a, T> { 270 | type Item = &'a T; 271 | fn next(&mut self) -> Option { 272 | if let Some(n) = self.current { 273 | let v = &n.value; 274 | // check if right, then right.leftmost, else right 275 | if let Some(r) = n.right.as_ref() { 276 | self.current = Some(r.leftmost(&mut self.stack)); 277 | } else { 278 | // go up stack 279 | self.current = self.stack.pop(); 280 | } 281 | Some(v) 282 | } else { 283 | None 284 | } 285 | } 286 | } 287 | 288 | impl From> for Vec { 289 | fn from(bst: BinarySearchTree) -> Self { 290 | let mut vec = Vec::new(); 291 | bst.traverse(&mut |v: T| vec.push(v)); 292 | vec 293 | } 294 | } 295 | 296 | impl From> for BinarySearchTree { 297 | fn from(vec: Vec) -> Self { 298 | let mut bst = BinarySearchTree::::new(); 299 | for v in vec { 300 | bst.insert(v); 301 | } 302 | bst 303 | } 304 | } 305 | 306 | #[cfg(test)] 307 | mod tests { 308 | use super::*; 309 | 310 | #[test] 311 | fn iterator_works() { 312 | let mut bst = BinarySearchTree::::new(); 313 | bst.insert(9); 314 | bst.insert(5); 315 | bst.insert(4); 316 | bst.insert(1); 317 | bst.insert(4); 318 | bst.insert(6); 319 | bst.insert(8); 320 | bst.insert(17); 321 | bst.insert(900); 322 | bst.insert(800); 323 | let v: Vec<&usize> = bst.iter().collect(); 324 | dbg!(&bst); 325 | let expected = vec![1, 4, 4, 5, 6, 8, 9, 17, 800, 900]; 326 | let expected: Vec<&usize> = expected.iter().collect(); 327 | assert_eq!(expected, v); 328 | } 329 | 330 | #[test] 331 | fn traverse_works() { 332 | let mut bst = BinarySearchTree::::new(); 333 | bst.insert(9); 334 | bst.insert(5); 335 | bst.insert(4); 336 | bst.insert(1); 337 | bst.insert(4); 338 | bst.insert(6); 339 | bst.insert(8); 340 | bst.insert(17); 341 | bst.insert(900); 342 | bst.insert(800); 343 | assert_eq!(vec![1, 4, 4, 5, 6, 8, 9, 17, 800, 900], Vec::from(bst)); 344 | } 345 | 346 | #[test] 347 | fn from_vec_works() { 348 | let vec = vec![3, 10, 0]; 349 | let bst = BinarySearchTree::from(vec); 350 | dbg!(&bst); 351 | assert!(bst.search(10)); 352 | assert!(bst.search(3)); 353 | assert!(bst.search(0)); 354 | } 355 | 356 | #[test] 357 | fn bst_works() { 358 | let mut bst = BinarySearchTree::::new(); 359 | bst.insert(10); 360 | bst.insert(7); 361 | bst.insert(15); 362 | bst.insert(9); 363 | bst.insert(4); 364 | bst.insert(17); 365 | bst.insert(3458); 366 | bst.insert(2000); 367 | assert!(bst.search(10)); 368 | assert!(bst.search(3458)); 369 | assert!(bst.search(4)); 370 | assert!(!bst.search(101)); 371 | assert!(!bst.search(383)); 372 | bst.insert(1); 373 | bst.insert(5); 374 | bst.insert(6); 375 | assert_eq!(Some(7), bst.delete(7)); 376 | bst.insert(4); 377 | assert_eq!(Some(6), bst.delete(6)); 378 | dbg!(&bst); 379 | assert_eq!(Some(3458), bst.delete(3458)); 380 | dbg!(&bst); 381 | assert_eq!(Some(15), bst.delete(15)); 382 | dbg!(&bst); 383 | bst.insert(1000); 384 | bst.insert(900); 385 | bst.insert(800); 386 | assert_eq!(Some(1000), bst.delete(1000)); 387 | dbg!(&bst); 388 | assert_eq!(Some(2000), bst.delete(2000)); 389 | dbg!(&bst); 390 | assert_eq!(Some(10), bst.delete(10)); 391 | dbg!(&bst); 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /src/doubly_linked_list.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | /* 3 | * DubLinkedList 4 | * Insert and remove from edges O(1)/constant time 5 | * get, Traversal is O(N) 6 | * new 7 | * push_front 8 | * push_back 9 | * pop_front 10 | * pop_back 11 | * get 12 | */ 13 | use std::cell::RefCell; 14 | use std::fmt; 15 | use std::ops::Deref; 16 | use std::rc::Rc; 17 | 18 | type Link = Rc>>; 19 | 20 | pub struct DubLinkedList { 21 | head: Option>, 22 | tail: Option>, 23 | len: usize, 24 | } 25 | 26 | impl fmt::Debug for DubLinkedList { 27 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 28 | write!(f, "DubLL {{ tail: {:?}, len: {:?} }}", self.tail, self.len) 29 | } 30 | } 31 | 32 | #[derive(Clone)] 33 | struct Node { 34 | val: T, 35 | prev: Option>, 36 | next: Option>, 37 | } 38 | 39 | impl fmt::Debug for Node { 40 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 41 | write!(f, "Node {{ val: {:?}, prev: {:?}}}", self.val, self.prev) 42 | } 43 | } 44 | 45 | impl DubLinkedList { 46 | pub fn new() -> DubLinkedList { 47 | DubLinkedList { 48 | head: None, 49 | tail: None, 50 | len: 0, 51 | } 52 | } 53 | 54 | pub fn push_front(&mut self, val: T) { 55 | if self.head.is_none() { 56 | let n = Node { 57 | val, 58 | prev: None, 59 | next: None, 60 | }; 61 | let link = Rc::new(RefCell::new(n)); 62 | self.tail = Some(Rc::clone(&link)); 63 | self.head = Some(link); 64 | self.len += 1; 65 | } else { 66 | let old_head = self.head.take().unwrap(); 67 | let n = Node { 68 | val, 69 | prev: None, 70 | next: Some(Rc::clone(&old_head)), 71 | }; 72 | let link = Rc::new(RefCell::new(n)); 73 | old_head.borrow_mut().prev = Some(Rc::clone(&link)); 74 | self.head = Some(link); 75 | self.len += 1; 76 | } 77 | } 78 | 79 | pub fn push_back(&mut self, val: T) { 80 | if self.tail.is_none() { 81 | let n = Node { 82 | val, 83 | prev: None, 84 | next: None, 85 | }; 86 | let link = Rc::new(RefCell::new(n)); 87 | self.tail = Some(Rc::clone(&link)); 88 | self.head = Some(link); 89 | self.len += 1; 90 | } else { 91 | let old_tail = self.tail.take().unwrap(); 92 | let n = Node { 93 | val, 94 | prev: Some(Rc::clone(&old_tail)), 95 | next: None, 96 | }; 97 | let link = Rc::new(RefCell::new(n)); 98 | old_tail.borrow_mut().next = Some(Rc::clone(&link)); 99 | self.tail = Some(link); 100 | self.len += 1; 101 | } 102 | } 103 | 104 | pub fn pop_front(&mut self) -> Option { 105 | if self.len == 0 { 106 | return None; 107 | } 108 | let head = self.head.take().unwrap(); 109 | let new_head = if let Some(link) = Rc::clone(&head).borrow_mut().next.take() { 110 | link.borrow_mut().prev = None; 111 | Some(link) 112 | } else { 113 | None 114 | }; 115 | 116 | self.len -= 1; 117 | self.head = new_head; 118 | if self.len == 0 { 119 | self.tail = None; 120 | } 121 | 122 | let n = match Rc::try_unwrap(head) { 123 | Ok(node) => node, 124 | Err(_) => panic!("we did bad thing in pop_front, how dare you!"), 125 | }; 126 | let v = n.into_inner().val; 127 | Some(v) 128 | } 129 | 130 | pub fn pop_back(&mut self) -> Option { 131 | if self.len == 0 { 132 | return None; 133 | } 134 | let tail = self.tail.take().unwrap(); 135 | let new_tail = if let Some(link) = Rc::clone(&tail).borrow_mut().prev.take() { 136 | link.borrow_mut().next = None; 137 | Some(link) 138 | } else { 139 | None 140 | }; 141 | 142 | self.len -= 1; 143 | self.tail = new_tail; 144 | if self.len == 0 { 145 | self.head = None; 146 | } 147 | 148 | let n = match Rc::try_unwrap(tail) { 149 | Ok(node) => node, 150 | Err(_) => panic!("we did a bad thing again in pop_back, wtaf!"), 151 | }; 152 | let v = n.into_inner().val; 153 | Some(v) 154 | } 155 | 156 | pub fn get(&self, index: usize) -> Option 157 | where 158 | T: Clone, 159 | { 160 | if index >= self.len { 161 | return None; 162 | } 163 | let mut node = self.head.as_ref().unwrap().borrow().deref().clone(); 164 | for _ in 1..=index { 165 | let n = node.next.as_ref(); 166 | let o = n.unwrap(); 167 | let next_node = o.borrow().deref().clone(); 168 | node = next_node; 169 | } 170 | Some(node.val.clone()) 171 | } 172 | } 173 | 174 | #[cfg(test)] 175 | mod tests { 176 | use super::*; 177 | 178 | #[test] 179 | fn dub_linked_list_works() { 180 | let mut l = DubLinkedList::::new(); 181 | assert_eq!(0, l.len); 182 | assert_eq!(None, l.pop_front()); 183 | l.push_front(200); 184 | l.push_front(-2); 185 | l.push_front(4123); 186 | assert_eq!(3, l.len); 187 | assert_eq!(Some(200), l.get(2)); 188 | assert_eq!(Some(-2), l.get(1)); 189 | assert_eq!(Some(4123), l.get(0)); 190 | assert_eq!(Some(4123), l.pop_front()); 191 | assert_eq!(Some(-2), l.pop_front()); 192 | assert_eq!(Some(200), l.pop_front()); 193 | assert_eq!(None, l.pop_front()); 194 | l.push_back(5000); 195 | l.push_front(-200); 196 | l.push_back(2); 197 | assert_eq!(3, l.len); 198 | // -200, 5000, 2 199 | assert_eq!(Some(-200), l.get(0)); 200 | assert_eq!(Some(5000), l.get(1)); 201 | assert_eq!(Some(2), l.get(2)); 202 | assert_eq!(Some(2), l.pop_back()); 203 | assert_eq!(Some(5000), l.pop_back()); 204 | assert_eq!(Some(-200), l.pop_back()); 205 | assert_eq!(None, l.pop_back()); 206 | l.pop_back(); 207 | assert_eq!(0, l.len); 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod array_list; 2 | pub mod binary_search_tree; 3 | pub mod doubly_linked_list; 4 | pub mod linked_list; 5 | pub mod priority_queue; 6 | pub mod queue; 7 | pub mod ring_buffer; 8 | pub mod stack; 9 | // rustonomicon reference implementation 10 | pub mod vec; 11 | 12 | pub fn add(left: usize, right: usize) -> usize { 13 | left + right 14 | } 15 | 16 | #[cfg(test)] 17 | mod lib_tests { 18 | use super::*; 19 | 20 | #[test] 21 | fn it_works() { 22 | let result = add(2, 2); 23 | assert_eq!(result, 4); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/linked_list.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | /* 3 | * LinkedList 4 | * Insert and remove from head/edges O(1)/constant time 5 | * get, Traversal is O(N) 6 | * new 7 | * push_front 8 | * get 9 | * pop_front 10 | */ 11 | use std::boxed::Box; 12 | 13 | pub struct LinkedList { 14 | head: Option>>, 15 | len: usize, 16 | } 17 | 18 | struct Node { 19 | val: T, 20 | next: Option>>, 21 | } 22 | 23 | impl LinkedList { 24 | pub fn new() -> LinkedList { 25 | LinkedList { head: None, len: 0 } 26 | } 27 | 28 | pub fn push_front(&mut self, val: T) { 29 | let prev_head = if let Some(node) = self.head.take() { 30 | Some(node) 31 | } else { 32 | None 33 | }; 34 | let n = Node { 35 | val, 36 | next: prev_head, 37 | }; 38 | self.len += 1; 39 | self.head = Some(Box::new(n)); 40 | } 41 | 42 | pub fn pop_front(&mut self) -> Option { 43 | if self.len == 0 { 44 | return None; 45 | } 46 | let mut head = self.head.take().unwrap(); 47 | let new_head = if let Some(node) = head.next.take() { 48 | Some(node) 49 | } else { 50 | None 51 | }; 52 | 53 | self.len -= 1; 54 | self.head = new_head; 55 | Some(head.val) 56 | } 57 | 58 | pub fn get(&self, index: usize) -> Option<&T> { 59 | if index >= self.len { 60 | return None; 61 | } 62 | let mut cell = self.head.as_ref().unwrap(); 63 | for _ in 1..=index { 64 | let next_cell = cell.next.as_ref().unwrap(); 65 | cell = next_cell; 66 | } 67 | Some(&cell.val) 68 | } 69 | } 70 | 71 | #[cfg(test)] 72 | mod tests { 73 | use super::*; 74 | 75 | #[test] 76 | fn linked_list_works() { 77 | let mut l = LinkedList::::new(); 78 | assert_eq!(0, l.len); 79 | assert_eq!(None, l.pop_front()); 80 | l.push_front(200); 81 | l.push_front(-2); 82 | l.push_front(4123); 83 | assert_eq!(3, l.len); 84 | assert_eq!(Some(&200), l.get(2)); 85 | assert_eq!(Some(&-2), l.get(1)); 86 | assert_eq!(Some(&4123), l.get(0)); 87 | assert_eq!(Some(4123), l.pop_front()); 88 | assert_eq!(Some(-2), l.pop_front()); 89 | assert_eq!(Some(200), l.pop_front()); 90 | assert_eq!(None, l.pop_front()); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/priority_queue.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | use std::collections::VecDeque; 3 | 4 | /** 5 | * Priority Queue aka MinHeap 6 | * Binary Tree-like data structure 7 | * Balanced: at most the height difference of nodes will be 1 8 | * Has heap condition: 9 | * in MinHeap: every Node under current Node is larger 10 | * in MaxHeap: every Node under current Node is smaller 11 | * the root O(log N) 12 | * Push to the bottom - bubbles up to find correct place, O(log N) 13 | */ 14 | #[derive(Debug)] 15 | struct PriorityQueue { 16 | queue: VecDeque, 17 | } 18 | 19 | impl PriorityQueue { 20 | pub fn new() -> Self { 21 | let mut queue = VecDeque::with_capacity(1); 22 | queue.push_back(T::default()); 23 | PriorityQueue { 24 | queue, 25 | } 26 | } 27 | 28 | pub fn len(&self) -> usize { 29 | self.queue.len() - 1 30 | } 31 | 32 | pub fn peak(&self) -> Option<&T> { 33 | if self.len() > 0 { 34 | Some(&self.queue[1]) 35 | } else { 36 | None 37 | } 38 | } 39 | 40 | pub fn pop(&mut self) -> Option { 41 | if self.len() == 0 { 42 | None 43 | } else if self.len() == 1 { 44 | self.queue.remove(1) 45 | } else { 46 | self.queue.swap(1, self.len()); 47 | let v = self.queue.pop_back(); 48 | self.heapify_down(1); 49 | v 50 | } 51 | } 52 | 53 | pub fn push(&mut self, value: T) { 54 | let i = self.queue.len(); 55 | self.queue.push_back(value); 56 | self.heapify_up(i); 57 | } 58 | 59 | fn left(&self, i: usize) -> (usize, Option<&T>) { 60 | let l_i = i * 2; 61 | (l_i, self.queue.get(l_i)) 62 | } 63 | 64 | fn right(&self, i: usize) -> (usize, Option<&T>) { 65 | let r_i = (i * 2) + 1; 66 | (r_i, self.queue.get(r_i)) 67 | } 68 | 69 | fn min_child (&self, i: usize) -> (usize, Option<&T>) { 70 | let (l_i, l) = self.left(i); 71 | let (r_i, r) = self.right(i); 72 | 73 | match (l, r) { 74 | (Some(l), Some(r)) if l > r => (r_i, Some(r)), 75 | (Some(l), _) => (l_i, Some(l)), 76 | _ => (0, None), 77 | } 78 | } 79 | 80 | /// Panics if i is out of bounds 81 | fn heapify_down(&mut self, i: usize) { 82 | let v = &self.queue[i]; 83 | // if min child is < v, swap with min child 84 | if let (c_i, Some(child)) = self.min_child(i) { 85 | if child < v { 86 | self.queue.swap(c_i, i); 87 | self.heapify_down(c_i); 88 | } 89 | } 90 | } 91 | 92 | fn heapify_up(&mut self, i: usize) { 93 | let parent_i = i/2; 94 | if parent_i != 0 { 95 | // compare to parent recursively and (maybe) swap 96 | if self.queue[i] < self.queue[parent_i] { 97 | self.queue.swap(i, parent_i); 98 | self.heapify_up(parent_i); 99 | } 100 | } 101 | } 102 | } 103 | 104 | #[cfg(test)] 105 | mod tests { 106 | use super::*; 107 | 108 | #[test] 109 | fn pq_works() { 110 | let mut pq = PriorityQueue::new(); 111 | assert_eq!(None, pq.peak()); 112 | assert_eq!(None, pq.pop()); 113 | pq.push(50); 114 | assert_eq!(Some(&50), pq.peak()); 115 | pq.push(75); 116 | pq.push(100); 117 | dbg!(&pq); 118 | assert_eq!(Some(&50), pq.peak()); 119 | pq.push(30); 120 | dbg!(&pq); 121 | assert_eq!(Some(&30), pq.peak()); 122 | assert_eq!(Some(30), pq.pop()); 123 | dbg!(&pq); 124 | assert_eq!(Some(50), pq.pop()); 125 | assert_eq!(Some(75), pq.pop()); 126 | assert_eq!(Some(100), pq.pop()); 127 | assert_eq!(None, pq.pop()); 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /src/queue.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | /* Queue: 3 | * FiFo - e.g. SQS, RabbitMQ 4 | * queue - adds to tail 5 | * deque - removes from head 6 | * peek - looks at next value in queue without consuming 7 | */ 8 | use std::fmt::Debug; 9 | 10 | use crate::doubly_linked_list::DubLinkedList; 11 | 12 | pub struct Queue { 13 | pub size: usize, 14 | list: DubLinkedList, 15 | } 16 | 17 | impl Queue { 18 | pub fn new() -> Queue { 19 | Queue { 20 | size: 0, 21 | list: DubLinkedList::::new(), 22 | } 23 | } 24 | 25 | pub fn queue(&mut self, item: T) { 26 | self.list.push_back(item); 27 | self.size += 1; 28 | } 29 | 30 | pub fn deque(&mut self) -> Option { 31 | if self.size != 0 { 32 | self.size -= 1; 33 | } 34 | self.list.pop_front() 35 | } 36 | 37 | pub fn peek(&self) -> Option 38 | where 39 | T: Clone, 40 | { 41 | self.list.get(0) 42 | } 43 | } 44 | 45 | #[cfg(test)] 46 | mod tests { 47 | use super::*; 48 | 49 | #[test] 50 | fn queue_works() { 51 | let mut q = Queue::::new(); 52 | q.deque(); 53 | assert_eq!(0, q.size); 54 | assert_eq!(None, q.peek()); 55 | q.queue(-34); 56 | assert_eq!(1, q.size); 57 | assert_eq!(Some(-34), q.peek()); 58 | q.queue(45); 59 | q.queue(3049); 60 | assert_eq!(3, q.size); 61 | assert_eq!(Some(-34), q.deque()); 62 | assert_eq!(Some(45), q.peek()); 63 | assert_eq!(Some(45), q.deque()); 64 | assert_eq!(Some(3049), q.peek()); 65 | assert_eq!(Some(3049), q.deque()); 66 | assert_eq!(0, q.size); 67 | assert_eq!(None, q.deque()); 68 | assert_eq!(0, q.size); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/ring_buffer.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | /* 3 | * RingBuffer 4 | * Uses an fixed-size array under the hood 5 | * stores length, index of head, index of tail 6 | * Array is padded at both head and tail so you can have O(1) benefit on both sides 7 | * If you exceed the size of array on either side, you can wrap around to the other, that is it's possible for actual index of head > tail 8 | * e.g. head may be at 4 and tail may be at 1 in a list of 10 elements 9 | * RingBuffer may describe this as head = 4, tail = 11 and to get actual index of tail you'd do `tail % len` which in the case would be 1 10 | * push_front 11 | * pop_back 12 | */ 13 | use std::alloc::Layout; 14 | use std::fmt::Debug; 15 | use std::mem; 16 | use std::ops::{Index, IndexMut}; 17 | use std::ptr::{self, NonNull}; 18 | 19 | pub struct RingBuffer { 20 | ptr: NonNull, 21 | head: Option, 22 | tail: Option, 23 | cap: usize, 24 | length: usize, 25 | } 26 | 27 | impl Debug for RingBuffer { 28 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 29 | f.debug_list().entries(self.iter()).finish() 30 | } 31 | } 32 | 33 | impl RingBuffer { 34 | /// if you allocate more memory than you have, this will panic 35 | fn allocate(cap: usize) -> NonNull { 36 | let layout = Layout::array::(cap).unwrap(); 37 | 38 | assert!(cap <= isize::MAX as usize, "Allocation too large!!!!!"); 39 | 40 | let raw_ptr = unsafe { std::alloc::alloc(layout) }; 41 | 42 | match NonNull::new(raw_ptr as *mut T) { 43 | Some(ptr) => ptr, 44 | None => std::alloc::handle_alloc_error(layout), 45 | } 46 | } 47 | 48 | pub fn new(cap: usize) -> Self { 49 | let ptr = Self::allocate(cap); 50 | RingBuffer { 51 | ptr, 52 | head: None, 53 | tail: None, 54 | cap, 55 | length: 0, 56 | } 57 | } 58 | 59 | /// panics if index is out of bounds 60 | fn offset(&self, index: usize) -> usize { 61 | (self.head.expect("index out of bounds") + index) % self.cap 62 | } 63 | 64 | fn before(&self, i: usize) -> usize { 65 | if i == 0 { 66 | self.cap - 1 67 | } else { 68 | i - 1 69 | } 70 | } 71 | 72 | pub fn push_front(&mut self, item: T) { 73 | // add el to head - 1 74 | let new_head = if let Some(old_i) = self.head.take() { 75 | self.before(old_i) 76 | } else { 77 | &self.cap / 4 78 | }; 79 | 80 | let is_overwrite = self.length == self.cap; 81 | 82 | unsafe { 83 | let p = self.ptr.as_ptr().add(new_head); 84 | if mem::needs_drop::() && is_overwrite { 85 | let v = ptr::read(p); 86 | drop(v); 87 | } 88 | ptr::write(p, item); 89 | } 90 | 91 | // update head 92 | self.head = Some(new_head); 93 | // update tail if length == cap 94 | if self.length == 0 { 95 | self.tail = Some(new_head); 96 | } else if is_overwrite { 97 | self.tail = self.tail.map(|i| self.before(i)); 98 | } 99 | // update length if length < cap 100 | if self.length < self.cap { 101 | self.length += 1; 102 | } 103 | } 104 | 105 | pub fn pop_back(&mut self) -> Option { 106 | // get el at tail 107 | let old_tail = if let Some(old_i) = self.tail.take() { 108 | old_i 109 | } else { 110 | return None; 111 | }; 112 | // decrement length 113 | self.length -= 1; 114 | // update tail to tail - 1 115 | if self.length > 0 { 116 | self.tail = Some(self.before(old_tail)); 117 | } 118 | // return el 119 | unsafe { Some(ptr::read(self.ptr.as_ptr().add(old_tail))) } 120 | } 121 | 122 | pub fn iter(&self) -> RingBufferIterator { 123 | RingBufferIterator { 124 | current_front: 0, 125 | current_back: self.length, 126 | buf: self, 127 | } 128 | } 129 | } 130 | 131 | impl Index for RingBuffer { 132 | type Output = T; 133 | /// Panics if index is out of bounds 134 | fn index(&self, index: usize) -> &Self::Output { 135 | if index < self.length { 136 | unsafe { 137 | self.ptr 138 | .as_ptr() 139 | .add(self.offset(index)) 140 | .as_ref() 141 | .expect("NPE how?") 142 | } 143 | } else { 144 | panic!("index out of bounds") 145 | } 146 | } 147 | } 148 | 149 | impl IndexMut for RingBuffer { 150 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { 151 | if index < self.length { 152 | unsafe { 153 | self.ptr 154 | .as_ptr() 155 | .add(self.offset(index)) 156 | .as_mut() 157 | .expect("NPE how?") 158 | } 159 | } else { 160 | panic!("index out of bounds") 161 | } 162 | } 163 | } 164 | 165 | pub struct RingBufferIterator<'a, T> { 166 | current_front: usize, 167 | current_back: usize, 168 | buf: &'a RingBuffer, 169 | } 170 | 171 | // this fn has been graciously donated by twitch.tv/laundmo 172 | impl<'a, T: Debug> Debug for RingBufferIterator<'a, T> { 173 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 174 | let mut listb = f.debug_list(); 175 | for i in self.current_front..self.current_back { 176 | listb.entry(&self.buf[i]); 177 | } 178 | listb.finish() 179 | } 180 | } 181 | 182 | impl<'a, T> Iterator for RingBufferIterator<'a, T> { 183 | type Item = &'a T; 184 | fn next(&mut self) -> Option { 185 | if self.current_front != self.current_back { 186 | let current_front = self.current_front; 187 | self.current_front += 1; 188 | Some(&self.buf[current_front]) 189 | } else { 190 | None 191 | } 192 | } 193 | } 194 | 195 | impl<'a, T> DoubleEndedIterator for RingBufferIterator<'a, T> { 196 | fn next_back(&mut self) -> Option { 197 | if self.current_front != self.current_back { 198 | self.current_back -= 1; 199 | Some(&self.buf[self.current_back]) 200 | } else { 201 | None 202 | } 203 | } 204 | } 205 | 206 | impl Drop for RingBuffer { 207 | fn drop(&mut self) { 208 | while let Some(i) = self.pop_back() { 209 | drop(i); 210 | } 211 | unsafe { 212 | std::alloc::dealloc( 213 | self.ptr.as_ptr() as *mut u8, 214 | Layout::array::(self.cap).unwrap(), 215 | ); 216 | } 217 | } 218 | } 219 | 220 | #[cfg(test)] 221 | mod tests { 222 | use super::*; 223 | 224 | #[test] 225 | fn ring_buffer_works() { 226 | let mut r = RingBuffer::::new(5); 227 | 228 | r.push_front(15); 229 | assert_eq!(15, r[0]); 230 | r.push_front(10); 231 | r.push_front(7); 232 | r.push_front(-5); 233 | r.push_front(75); 234 | r.push_front(-2340); 235 | assert_eq!(-2340, r[0]); 236 | assert_eq!(10, r[4]); 237 | assert_eq!(7, r[3]); 238 | assert_eq!(Some(10), r.pop_back()); 239 | assert_eq!(Some(7), r.pop_back()); 240 | r.push_front(-3498); 241 | r.push_front(8383); 242 | assert_eq!(Some(-5), r.pop_back()); 243 | assert_eq!(Some(75), r.pop_back()); 244 | assert_eq!(Some(-2340), r.pop_back()); 245 | assert_eq!(Some(-3498), r.pop_back()); 246 | assert_eq!(Some(8383), r.pop_back()); 247 | assert_eq!(None, r.pop_back()); 248 | } 249 | 250 | #[test] 251 | fn index_mut_works() { 252 | let mut r = RingBuffer::::new(5); 253 | r.push_front(24); 254 | r.push_front(-20); 255 | r.push_front(-245); 256 | assert_eq!(24, r[2]); 257 | r[2] = -45; 258 | assert_eq!(-45, r[2]); 259 | assert_eq!(Some(-45), r.pop_back()); 260 | for i in 0..r.length { 261 | dbg!(r[i]); 262 | } 263 | } 264 | 265 | #[test] 266 | fn box_rb_works() { 267 | let mut r = RingBuffer::>::new(5); 268 | r.push_front(Box::new("hello".to_string())); 269 | r.push_front(Box::new("hey".to_string())); 270 | r.push_front(Box::new("hola".to_string())); 271 | r.push_front(Box::new("gutentag".to_string())); 272 | r.push_front(Box::new("ohaiyo".to_string())); 273 | r.push_front(Box::new("sup".to_string())); 274 | assert_eq!(Some("hey".to_string()), r.pop_back().map(|b| *b)); 275 | assert_eq!(Box::new("gutentag".to_string()), r[2]); 276 | } 277 | 278 | #[test] 279 | fn iter_tests() { 280 | let mut r = RingBuffer::::new(5); 281 | r.push_front(5.5); 282 | r.push_front(8.2); 283 | r.push_front(9.1); 284 | r.push_front(6.3); 285 | r.push_front(1.5436); 286 | 287 | let mut i = 0; 288 | for e in r.iter() { 289 | dbg!(e); 290 | i += 1; 291 | } 292 | 293 | assert_eq!(i, r.length); 294 | 295 | let mut iter = r.iter(); 296 | assert_eq!(Some(&5.5), iter.nth(4)); 297 | assert!(r.iter().fold(0f64, |x, y| x + y) > 0f64); 298 | 299 | let mut i2 = r.iter(); 300 | assert_eq!(Some(&5.5), i2.next_back()); 301 | assert_eq!(Some(&8.2), i2.rev().nth(0)); 302 | 303 | let mut i3 = r.iter(); 304 | dbg!(&i3); 305 | assert_eq!(Some(&8.2), i3.nth(3)); 306 | dbg!(&i3); 307 | assert_eq!(Some(&5.5), i3.next_back()); 308 | dbg!(&i3); 309 | assert_eq!(None, i3.next_back()); 310 | dbg!(&i3); 311 | assert_eq!(None, i3.next()); 312 | dbg!(&i3); 313 | } 314 | } 315 | -------------------------------------------------------------------------------- /src/stack.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | /* 3 | Stack: 4 | * LiFo queue 5 | * pop/push of O(1) 6 | */ 7 | use std::alloc::{self, Layout}; 8 | use std::mem; 9 | use std::ptr::{self, NonNull}; 10 | 11 | pub struct Stack { 12 | ptr: NonNull, 13 | cap: usize, 14 | len: usize, 15 | } 16 | 17 | unsafe impl Send for Stack {} 18 | unsafe impl Sync for Stack {} 19 | 20 | impl Stack { 21 | pub fn new() -> Stack { 22 | Stack { 23 | ptr: NonNull::dangling(), 24 | cap: 0, 25 | len: 0, 26 | } 27 | } 28 | 29 | fn grow(&mut self) { 30 | let (new_cap, layout) = if self.cap == 0 { 31 | (1, Layout::array::(1).unwrap()) 32 | } else { 33 | let new_cap = self.cap * 2; 34 | 35 | assert!(new_cap <= isize::MAX as usize, "Allocation too large!!!!!"); 36 | 37 | (new_cap, Layout::array::(self.cap).unwrap()) 38 | }; 39 | 40 | let ptr = if self.cap == 0 { 41 | unsafe { alloc::alloc(layout) } 42 | } else { 43 | let new_size = new_cap * mem::size_of::(); 44 | unsafe { alloc::realloc(self.ptr.as_ptr() as *mut u8, layout, new_size) } 45 | }; 46 | 47 | self.cap = new_cap; 48 | match NonNull::new(ptr as *mut T) { 49 | Some(ptr) => { 50 | self.ptr = ptr; 51 | } 52 | None => alloc::handle_alloc_error(layout), 53 | } 54 | } 55 | 56 | pub fn pop(&mut self) -> Option { 57 | if self.len == 0 { 58 | None 59 | } else { 60 | self.len -= 1; 61 | unsafe { Some(ptr::read(self.ptr.as_ptr().add(self.len))) } 62 | } 63 | } 64 | 65 | pub fn push(&mut self, item: T) { 66 | // item = 1, len = 5, cap = 8 67 | if self.cap == self.len { 68 | self.grow(); 69 | } 70 | 71 | unsafe { 72 | ptr::write(self.ptr.as_ptr().add(self.len), item); 73 | } 74 | self.len += 1; 75 | } 76 | } 77 | 78 | impl Drop for Stack { 79 | fn drop(&mut self) { 80 | while let Some(item) = self.pop() { 81 | drop(item); 82 | } 83 | unsafe { 84 | alloc::dealloc( 85 | self.ptr.as_ptr() as *mut u8, 86 | Layout::array::(self.cap).unwrap(), 87 | ); 88 | } 89 | } 90 | } 91 | 92 | #[cfg(test)] 93 | mod tests { 94 | use super::*; 95 | 96 | #[test] 97 | fn stack_works() { 98 | let mut s = Stack::::new(); 99 | assert_eq!(None, s.pop()); 100 | assert_eq!(0, s.len); 101 | s.push(5); 102 | assert_eq!(1, s.len); 103 | assert_eq!(Some(5), s.pop()); 104 | s.push(4); 105 | assert_eq!(1, s.cap); 106 | s.push(10); 107 | assert_eq!(2, s.len); 108 | for n in 1..=1000 { 109 | s.push(n); 110 | } 111 | for _ in 1..=10 { 112 | s.pop(); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/vec.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code, warnings)] 2 | /* 3 | Reference implementation of MyVec taken from Rustonomicon: 4 | https://doc.rust-lang.org/nomicon/vec 5 | Purposefully left incomplete but will be used for a reference for unsafe rust actions when implementing the rest of our DSs 6 | */ 7 | 8 | use std::alloc::{self, Layout}; 9 | use std::mem::{self, ManuallyDrop}; 10 | use std::ptr::{self, NonNull}; 11 | 12 | pub struct MyVec { 13 | ptr: NonNull, 14 | cap: usize, 15 | len: usize, 16 | } 17 | 18 | unsafe impl Send for MyVec {} 19 | unsafe impl Sync for MyVec {} 20 | 21 | impl MyVec { 22 | pub fn new() -> Self { 23 | assert!(mem::size_of::() != 0, "We're not ready to handle ZSTs"); 24 | MyVec { 25 | ptr: NonNull::dangling(), 26 | len: 0, 27 | cap: 0, 28 | } 29 | } 30 | 31 | fn grow(&mut self) { 32 | let (new_cap, new_layout) = if self.cap == 0 { 33 | (1, Layout::array::(1).unwrap()) 34 | } else { 35 | let new_cap = 2 * self.cap; 36 | let new_layout = Layout::array::(new_cap).unwrap(); 37 | (new_cap, new_layout) 38 | }; 39 | 40 | assert!( 41 | new_layout.size() <= isize::MAX as usize, 42 | "Allocation too large" 43 | ); 44 | 45 | let new_ptr = if self.cap == 0 { 46 | unsafe { alloc::alloc(new_layout) } 47 | } else { 48 | let old_layout = Layout::array::(self.cap).unwrap(); 49 | let old_ptr = self.ptr.as_ptr() as *mut u8; 50 | unsafe { alloc::realloc(old_ptr, old_layout, new_layout.size()) } 51 | }; 52 | 53 | self.ptr = match NonNull::new(new_ptr as *mut T) { 54 | Some(p) => p, 55 | None => alloc::handle_alloc_error(new_layout), 56 | }; 57 | self.cap = new_cap; 58 | } 59 | 60 | pub fn push(&mut self, elem: T) { 61 | if self.len == self.cap { 62 | self.grow(); 63 | } 64 | 65 | unsafe { 66 | ptr::write(self.ptr.as_ptr().add(self.len), elem); 67 | } 68 | 69 | self.len = self.len + 1; 70 | } 71 | 72 | pub fn pop(&mut self) -> Option { 73 | if self.len == 0 { 74 | None 75 | } else { 76 | self.len -= 1; 77 | unsafe { Some(ptr::read(self.ptr.as_ptr().add(self.len))) } 78 | } 79 | } 80 | 81 | pub fn insert(&mut self, index: usize, elem: T) { 82 | // Note: `<=` because it's valid to insert after everything 83 | // which would be equivalent to push. 84 | assert!(index <= self.len, "index out of bounds"); 85 | if self.cap == self.len { 86 | self.grow(); 87 | } 88 | 89 | unsafe { 90 | // ptr::copy(src, dest, len): "copy from src to dest len elems" 91 | ptr::copy( 92 | self.ptr.as_ptr().add(index), 93 | self.ptr.as_ptr().add(index + 1), 94 | self.len - index, 95 | ); 96 | ptr::write(self.ptr.as_ptr().add(index), elem); 97 | self.len += 1; 98 | } 99 | } 100 | 101 | pub fn remove(&mut self, index: usize) -> T { 102 | // Note: `<` because it's *not* valid to remove after everything 103 | assert!(index < self.len, "index out of bounds"); 104 | unsafe { 105 | self.len -= 1; 106 | let result = ptr::read(self.ptr.as_ptr().add(index)); 107 | ptr::copy( 108 | self.ptr.as_ptr().add(index + 1), 109 | self.ptr.as_ptr().add(index), 110 | self.len - index, 111 | ); 112 | result 113 | } 114 | } 115 | } 116 | 117 | impl Drop for MyVec { 118 | fn drop(&mut self) { 119 | if self.cap != 0 { 120 | while let Some(_) = self.pop() {} 121 | let layout = Layout::array::(self.cap).unwrap(); 122 | unsafe { 123 | alloc::dealloc(self.ptr.as_ptr() as *mut u8, layout); 124 | } 125 | } 126 | } 127 | } 128 | 129 | use std::ops::Deref; 130 | 131 | impl Deref for MyVec { 132 | type Target = [T]; 133 | fn deref(&self) -> &[T] { 134 | unsafe { std::slice::from_raw_parts(self.ptr.as_ptr(), self.len) } 135 | } 136 | } 137 | 138 | use std::ops::DerefMut; 139 | 140 | impl DerefMut for MyVec { 141 | fn deref_mut(&mut self) -> &mut [T] { 142 | unsafe { std::slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) } 143 | } 144 | } 145 | 146 | pub struct IntoIter { 147 | buf: NonNull, 148 | cap: usize, 149 | start: *const T, 150 | end: *const T, 151 | } 152 | 153 | impl IntoIterator for MyVec { 154 | type Item = T; 155 | type IntoIter = IntoIter; 156 | fn into_iter(self) -> IntoIter { 157 | let vec = ManuallyDrop::new(self); 158 | 159 | let ptr = vec.ptr; 160 | let cap = vec.cap; 161 | let len = vec.len; 162 | 163 | unsafe { 164 | IntoIter { 165 | buf: ptr, 166 | cap, 167 | start: ptr.as_ptr(), 168 | end: if cap == 0 { 169 | ptr.as_ptr() 170 | } else { 171 | ptr.as_ptr().add(len) 172 | }, 173 | } 174 | } 175 | } 176 | } 177 | 178 | impl Iterator for IntoIter { 179 | type Item = T; 180 | fn next(&mut self) -> Option { 181 | if self.start == self.end { 182 | None 183 | } else { 184 | unsafe { 185 | let result = ptr::read(self.start); 186 | self.start = self.start.offset(1); 187 | Some(result) 188 | } 189 | } 190 | } 191 | 192 | fn size_hint(&self) -> (usize, Option) { 193 | let len = (self.end as usize - self.start as usize) / mem::size_of::(); 194 | (len, Some(len)) 195 | } 196 | } 197 | 198 | impl DoubleEndedIterator for IntoIter { 199 | fn next_back(&mut self) -> Option { 200 | if self.start == self.end { 201 | None 202 | } else { 203 | unsafe { 204 | self.end = self.end.offset(-1); 205 | Some(ptr::read(self.end)) 206 | } 207 | } 208 | } 209 | } 210 | 211 | impl Drop for IntoIter { 212 | fn drop(&mut self) { 213 | if self.cap != 0 { 214 | for _ in &mut *self {} 215 | let layout = Layout::array::(self.cap).unwrap(); 216 | unsafe { 217 | alloc::dealloc(self.buf.as_ptr() as *mut u8, layout); 218 | } 219 | } 220 | } 221 | } 222 | 223 | #[cfg(test)] 224 | mod test { 225 | use super::*; 226 | 227 | #[test] 228 | fn vec_works() { 229 | dbg!(std::mem::size_of::>()); 230 | dbg!(std::mem::size_of::>()); 231 | dbg!(std::mem::align_of::>()); 232 | dbg!(std::mem::align_of::>()); 233 | dbg!(std::mem::size_of::>()); 234 | dbg!(Layout::array::(1).unwrap()); 235 | dbg!(Layout::array::(5).unwrap()); 236 | dbg!(Layout::array::(1).unwrap()); 237 | dbg!(Layout::array::(5).unwrap()); 238 | assert!(true); 239 | } 240 | } 241 | -------------------------------------------------------------------------------- /tests/thread_tests.rs: -------------------------------------------------------------------------------- 1 | use rust_dsa::doubly_linked_list::DubLinkedList; 2 | use rust_dsa::linked_list::LinkedList; 3 | use rust_dsa::stack::Stack; 4 | use std::thread; 5 | 6 | #[test] 7 | fn thread_tests() { 8 | let mut s = Stack::::new(); 9 | s.push(1); 10 | s.push(5); 11 | s.push(10); 12 | 13 | let handle = thread::spawn(move || { 14 | println!("{:?}", s.pop()); 15 | s.pop() 16 | }); 17 | 18 | // println!("{x:?}"); 19 | 20 | /* 21 | let handle2 = thread::spawn(move || { 22 | let e = s.as_ref().pop(); 23 | println!("pop that {e:?} off"); 24 | }); 25 | */ 26 | // println!("stack {s:?}"); 27 | println!("{:?}", handle.join().unwrap()); 28 | // handle2.join().unwrap(); 29 | 30 | let mut dl = DubLinkedList::::new(); 31 | 32 | dl.push_front(5); 33 | 34 | // yay, rust compiler doesn't let us move an Rc, Rust W 35 | // thread::spawn(move || { 36 | // dl.push_back(10); 37 | // println!("{:?}", dl.pop_front()); 38 | // }); 39 | 40 | let mut ll = LinkedList::::new(); 41 | ll.push_front(45); 42 | ll.push_front(47); 43 | let handle = thread::spawn(move || { 44 | ll.pop_front(); 45 | ll 46 | }); 47 | let ll = handle.join().unwrap(); 48 | assert_eq!(Some(&45), ll.get(0)); 49 | assert!(true); 50 | } 51 | --------------------------------------------------------------------------------