Add Double Singly-Linked list example
This commit is contained in:
parent
0e92a87719
commit
07d33735c6
@ -3,3 +3,5 @@ pub mod second;
|
||||
pub mod third;
|
||||
pub mod fourth;
|
||||
pub mod fifth;
|
||||
|
||||
pub mod silly1;
|
||||
|
140
src/silly1.rs
Normal file
140
src/silly1.rs
Normal file
@ -0,0 +1,140 @@
|
||||
//! # The Double Singly-Linked List
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct List<T> {
|
||||
left: Stack<T>,
|
||||
right: Stack<T>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Stack<T> {
|
||||
head: Link<T>,
|
||||
}
|
||||
|
||||
type Link<T> = Option<Box<Node<T>>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Node<T> {
|
||||
elem: T,
|
||||
next: Link<T>,
|
||||
}
|
||||
|
||||
impl<T> Stack<T> {
|
||||
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<T>>) {
|
||||
node.next = self.head.take();
|
||||
self.head = Some(node);
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Option<T> {
|
||||
self.pop_node().map(|node| {
|
||||
node.elem
|
||||
})
|
||||
}
|
||||
|
||||
fn pop_node(&mut self) -> Link<T> {
|
||||
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<T> Drop for Stack<T> {
|
||||
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<T> List<T> {
|
||||
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<T> { self.left.pop() }
|
||||
pub fn pop_right(&mut self) -> Option<T> { 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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user