added simple linked list

This commit is contained in:
Ed Guloien
2026-06-01 15:49:39 -04:00
commit e9550db4b3
4 changed files with 116 additions and 0 deletions
+102
View File
@@ -0,0 +1,102 @@
struct List { head: Option<Box<Node>>, len: usize }
struct Node {
value: u32,
next: Option<Box<Node>>
}
impl List {
pub fn new() -> Self {
List { head: None, len: 0}
}
pub fn append(&mut self, val: u32) {
let slot = self.walk(self.len);
*slot = Some(Box::new(Node{value: val, next: None}));
self.len += 1;
}
pub fn insert(&mut self, val: u32, index: usize) {
let slot = self.walk(index);
let rest = slot.take();
*slot = Some(Box::new(Node { value: val, next: rest }));
self.len += 1;
}
pub fn remove(&mut self, index: usize) -> Option<u32> {
if index >= self.len {
return None;
}
let slot = self.walk(index);
let removed = slot.take()?;
*slot = removed.next;
self.len -= 1;
Some(removed.value)
}
// walk returns the entry at index
fn walk(&mut self, index: usize) -> &mut Option<Box<Node>> {
let mut iter = &mut self.head;
for _ in 0..index {
match iter {
Some(node) => iter = &mut node.next,
None => break,
}
}
iter
}
pub fn as_vec(&self) -> Vec<u32> {
let mut result = Vec::new();
let mut i = &self.head;
while let Some(node) = i {
result.push(node.value);
i = &node.next;
}
result
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
}
fn main() {
println!("use cargo test");
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_list() {
let mut l = List::new();
l.append(1);
l.append(2);
l.append(3);
l.append(4);
assert_eq!(l.as_vec(), vec![1,2,3,4]);
l.remove(2);
assert_eq!(l.as_vec(), vec![1,2,4]);
l.remove(2);
assert_eq!(l.as_vec(), vec![1,2]);
l.remove(2); // too far, no removal
assert_eq!(l.as_vec(), vec![1,2]);
l.insert(5, 1);
assert_eq!(l.as_vec(), vec![1,5,2]);
l.insert(6, 3);
assert_eq!(l.as_vec(), vec![1,5,2,6]);
l.remove(0);
assert_eq!(l.as_vec(), vec![5,2,6]);
l.remove(0);
assert_eq!(l.as_vec(), vec![2,6]);
l.remove(0);
assert_eq!(l.as_vec(), vec![6]);
l.remove(0);
assert!(l.is_empty());
}
}