Simple Linked List
1. Readme
简单链表
编写一个使用元素(Elements
)和列表(List
)的简单链表实现.
链表是计算机科学中的一种基本数据结构,常用于其他数据结构的实现。它们在函数式编程语言(如 Clojure、Erlang 或 Haskell)中很普遍,但是在命令式语言(如 Ruby 或 Python)中很少见。
最简单的链表是单链表。列表中的每个元素,包含数据和一个”next”字段,指向元素列表中的下一个元素。
链接列表的这种变体通常用于表示序列,或推/取堆栈(也称为 LIFO 堆栈;后进先出)。
作为第一步,让我们创建一个包含范围(1..10)的单一链接列表,并提供反转链接列表,和转换为数组,或从数组转换的函数.
在使用内置链表的语言实现这一点时,实现自己的抽象数据类型.
实现提示
不要实现结构SimpleLinkedList
作为一个Vec
包装。 你应该,在堆上分配节点。
这可以实现为:
# #![allow(unused_variables)] #fn main() { pub struct SimpleLinkedList<T> { head: Option<Box<Node<T>>>, } #}
这个head
字段指向该链表的第一个元素(节点)。
这个实现也需要一个Node
结构,其具有以下字段:
# #![allow(unused_variables)] #fn main() { struct Node<T> { data: T, next: Option<Box<Node<T>>>, } #}
data
包含存储的数据,以及next
指向下节点(如果可用)或无.
为什么使用Option<Box<Node<T>>>
?而不仅用Option<Node<T>>
?
自己试试.您将得到以下错误.
| struct Node<T>
| ^^^^^^^^^^^^^^ recursive type has infinite size
...
| next: Option<Node<T>>,
| --------------------- recursive without indirection
这个错误在于,编译时,rust 必须知道下一个节点的大小。因next
会是递归的(”一个节点,有一个节点-有一个节点…”),编译器不知道要分配多少内存。相反,Box是一个具有定义大小的堆指针.
资源
受”Ruby”中面向对象设计模式的数据结构和算法的启发,即单链表.http://www.brpreiss.com/books/opus8/html/page96.html#SECTION004300000000000000000
2. 开始你的表演
pub struct SimpleLinkedList<T> { // Delete this field // dummy is needed to avoid unused parameter error during compilation dummy: ::std::marker::PhantomData<T>, } impl<T> SimpleLinkedList<T> { pub fn new() -> Self { unimplemented!() } pub fn len(&self) -> usize { unimplemented!() } pub fn push(&mut self, _element: T) { unimplemented!() } pub fn pop(&mut self) -> Option<T> { unimplemented!() } pub fn peek(&self) -> Option<&T> { unimplemented!() } } impl<T: Clone> SimpleLinkedList<T> { pub fn rev(&self) -> SimpleLinkedList<T> { unimplemented!() } } impl<'a, T: Clone> From<&'a [T]> for SimpleLinkedList<T> { fn from(_item: &[T]) -> Self { unimplemented!() } } impl<T> Into<Vec<T>> for SimpleLinkedList<T> { fn into(self) -> Vec<T> { unimplemented!() } }
3. 测试代码查看
# #![allow(unused_variables)] #fn main() { #[test] fn test_new_list_is_empty() { let list: SimpleLinkedList<u32> = SimpleLinkedList::new(); assert_eq!(list.len(), 0, "list's length must be 0"); } #[test] //#[ignore] fn test_push_increments_length() { let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new(); list.push(1); assert_eq!(list.len(), 1, "list's length must be 1"); list.push(2); assert_eq!(list.len(), 2, "list's length must be 2"); } #[test] //#[ignore] fn test_pop_decrements_length() { let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new(); list.push(1); list.push(2); list.pop(); assert_eq!(list.len(), 1, "list's length must be 1"); list.pop(); assert_eq!(list.len(), 0, "list's length must be 0"); } #[test] //#[ignore] fn test_pop_returns_last_added_element() { let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new(); list.push(1); list.push(2); assert_eq!(list.pop(), Some(2), "Element must be 2"); assert_eq!(list.pop(), Some(1), "Element must be 1"); assert_eq!(list.pop(), None, "No element should be contained in list"); } #[test] //#[ignore] fn test_peek_returns_head_element() { let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new(); assert_eq!(list.peek(), None, "No element should be contained in list"); list.push(2); assert_eq!(list.peek(), Some(&2), "Element must be 2"); assert_eq!(list.peek(), Some(&2), "Element must be still 2"); } #[test] //#[ignore] fn test_from_slice() { let array = ["1", "2", "3", "4"]; let mut list = SimpleLinkedList::from(array.as_ref()); assert_eq!(list.pop(), Some("4")); assert_eq!(list.pop(), Some("3")); assert_eq!(list.pop(), Some("2")); assert_eq!(list.pop(), Some("1")); } #[test] //#[ignore] fn test_reverse() { let mut list: SimpleLinkedList<u32> = SimpleLinkedList::new(); list.push(1); list.push(2); list.push(3); let mut rev_list = list.rev(); assert_eq!(rev_list.pop(), Some(1)); assert_eq!(rev_list.pop(), Some(2)); assert_eq!(rev_list.pop(), Some(3)); assert_eq!(rev_list.pop(), None); } #[test] //#[ignore] fn test_into_vector() { let mut v = Vec::new(); let mut s = SimpleLinkedList::new(); for i in 1..4 { v.push(i); s.push(i); } let s_as_vec: Vec<i32> = s.into(); assert_eq!(v, s_as_vec); } #}
4. 答案
# #![allow(unused_variables)] #fn main() { pub struct SimpleLinkedList<T> { head: Option<Box<Node<T>>>, len: usize, } struct Node<T> { data: T, next: Option<Box<Node<T>>>, } impl<T> SimpleLinkedList<T> { pub fn new() -> Self { SimpleLinkedList { head: None, len: 0 } } pub fn len(&self) -> usize { self.len } pub fn push(&mut self, element: T) { let node = Box::new(Node::new(element, self.head.take())); self.head = Some(node); self.len += 1; } pub fn pop(&mut self) -> Option<T> { match self.len { 0 => None, _ => { self.len -= 1; self.head.take().map(|node| { let node = *node; self.head = node.next; node.data }) } } } pub fn peek(&self) -> Option<&T> { self.head.as_ref().map(|node| &node.data) } } impl<T: Clone> SimpleLinkedList<T> { pub fn rev(&self) -> SimpleLinkedList<T> { let mut rev_list = SimpleLinkedList::new(); let mut next = self.head.as_ref().map(|node| &**node); while let Some(node) = next { rev_list.push(node.data.clone()); next = node.next.as_ref().map(|node| &**node); } rev_list } } impl<'a, T: Clone> From<&'a [T]> for SimpleLinkedList<T> { fn from(item: &[T]) -> Self { let mut list = SimpleLinkedList::new(); for i in item { list.push(i.clone()); } list } } impl<T> Into<Vec<T>> for SimpleLinkedList<T> { fn into(mut self) -> Vec<T> { let mut vec = Vec::new(); while let Some(data) = self.pop() { vec.push(data); } vec.reverse(); vec } } impl<T> Node<T> { pub fn new(element: T, next: Option<Box<Node<T>>>) -> Self { Node { data: element, next, } } } #}