From 07d33735c61971b65aacccb8bc90b0b9e47fada7 Mon Sep 17 00:00:00 2001 From: Timothy Warren Date: Wed, 13 Mar 2019 12:34:22 -0400 Subject: [PATCH] Add Double Singly-Linked list example --- src/lib.rs | 2 + src/silly1.rs | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/silly1.rs diff --git a/src/lib.rs b/src/lib.rs index 4d2d0c6..73df62e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,3 +3,5 @@ pub mod second; pub mod third; pub mod fourth; pub mod fifth; + +pub mod silly1; diff --git a/src/silly1.rs b/src/silly1.rs new file mode 100644 index 0000000..d94d6b2 --- /dev/null +++ b/src/silly1.rs @@ -0,0 +1,140 @@ +//! # The Double Singly-Linked List + +#[derive(Debug)] +pub struct List { + left: Stack, + right: Stack, +} + +#[derive(Debug)] +pub struct Stack { + head: Link, +} + +type Link = Option>>; + +#[derive(Debug)] +struct Node { + elem: T, + next: Link, +} + +impl Stack { + pub fn new() -> Self { + Stack { head: None } + } + + pub fn push(&mut self, elem: T) { + let new_node = Box::new(Node { + elem, + next: None, + }); + + self.push_node(new_node); + } + + fn push_node(&mut self, mut node: Box>) { + node.next = self.head.take(); + self.head = Some(node); + } + + pub fn pop(&mut self) -> Option { + self.pop_node().map(|node| { + node.elem + }) + } + + fn pop_node(&mut self) -> Link { + self.head.take().map(|mut node| { + self.head = node.next.take(); + node + }) + } + + pub fn peek(&self) -> Option<&T> { + self.head.as_ref().map(|node| { + &node.elem + }) + } + + pub fn peek_mut(&mut self) -> Option<&mut T> { + self.head.as_mut().map(|node| { + &mut node.elem + }) + } +} + +impl Drop for Stack { + fn drop(&mut self) { + let mut cur_link = self.head.take(); + while let Some(mut boxed_node) = cur_link { + cur_link = boxed_node.next.take(); + } + } +} + + +impl List { + pub fn new() -> Self { + List{ + left: Stack::new(), + right: Stack::new(), + } + } + + pub fn push_left(&mut self, elem: T) { self.left.push(elem) } + pub fn push_right(&mut self, elem: T) { self.right.push(elem) } + pub fn pop_left(&mut self) -> Option { self.left.pop() } + pub fn pop_right(&mut self) -> Option { self.right.pop() } + pub fn peek_left(&self) -> Option<&T> { self.left.peek() } + pub fn peek_right(&self) -> Option<&T> { self.right.peek() } + pub fn peek_left_mut(&mut self) -> Option<&mut T> { self.left.peek_mut() } + pub fn peek_right_mut(&mut self) -> Option<&mut T> { self.right.peek_mut() } + + pub fn go_left(&mut self) -> bool { + self.left.pop_node().map(|node| { + self.right.push_node(node); + }).is_some() + } + + pub fn go_right(&mut self) -> bool { + self.right.pop_node().map(|node| { + self.left.push_node(node); + }).is_some() + } +} + +#[cfg(test)] +mod test { + use super::List; + + #[test] + fn walk_aboot() { + let mut list = List::new(); // [_] + + list.push_left(0); // [0,_] + list.push_right(1); // [0, _, 1] + assert_eq!(list.peek_left(), Some(&0)); + assert_eq!(list.peek_right(), Some(&1)); + + list.push_left(2); // [0, 2, _, 1] + list.push_left(3); // [0, 2, 3, _, 1] + list.push_right(4); // [0, 2, 3, _, 4, 1] + + while list.go_left() {} // [_, 0, 2, 3, 4, 1] + + assert_eq!(list.pop_left(), None); + assert_eq!(list.peek_right(), Some(&0)); + assert_eq!(list.pop_right(), Some(0)); // [_, 2, 3, 4, 1] + assert_eq!(list.pop_right(), Some(2)); // [_, 3, 4, 1] + + list.push_left(5); // [5, _, 3, 4, 1] + assert_eq!(list.pop_right(), Some(3)); // [5, _, 4, 1] + assert_eq!(list.pop_left(), Some(5)); // [_, 4, 1] + assert_eq!(list.pop_right(), Some(4)); // [_, 1] + assert_eq!(list.pop_right(), Some(1)); // [_] + + assert_eq!(list.pop_right(), None); + assert_eq!(list.pop_left(), None); + } +}