|
|
@ -20,3 +20,201 @@ struct List<T> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
这里将之前的 `List` 引入进来,并重命名为 `Stack`,接着,创建一个新的链表。现在既可以向左增长又可以向右增长。
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
|
|
pub struct Stack<T> {
|
|
|
|
|
|
|
|
head: Link<T>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type Link<T> = Option<Box<Node<T>>>;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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: elem,
|
|
|
|
|
|
|
|
next: self.head.take(),
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
self.head = Some(new_node);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn pop(&mut self) -> Option<T> {
|
|
|
|
|
|
|
|
self.head.take().map(|node| {
|
|
|
|
|
|
|
|
let node = *node;
|
|
|
|
|
|
|
|
self.head = node.next;
|
|
|
|
|
|
|
|
node.elem
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
稍微修改下 `push` 和 `pop`:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
|
|
pub fn push(&mut self, elem: T) {
|
|
|
|
|
|
|
|
let new_node = Box::new(Node {
|
|
|
|
|
|
|
|
elem: 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) -> Option<Box<Node<T>>> {
|
|
|
|
|
|
|
|
self.head.take().map(|mut node| {
|
|
|
|
|
|
|
|
self.head = node.next.take();
|
|
|
|
|
|
|
|
node
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
现在可以开始构造新的链表:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
|
|
pub struct List<T> {
|
|
|
|
|
|
|
|
left: Stack<T>,
|
|
|
|
|
|
|
|
right: Stack<T>,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl<T> List<T> {
|
|
|
|
|
|
|
|
fn new() -> Self {
|
|
|
|
|
|
|
|
List { left: Stack::new(), right: Stack::new() }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
当然,还有一大堆左左右右类型的操作:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
|
|
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() }
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
其中最有趣的是:还可以来回闲逛了。
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
这里返回 `bool` 是为了告诉调用者我们是否成功的移动。最后,再来测试下:
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
|
|
|
#[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.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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
```shell
|
|
|
|
|
|
|
|
> cargo test
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Running target/debug/lists-5c71138492ad4b4a
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
running 16 tests
|
|
|
|
|
|
|
|
test fifth::test::into_iter ... ok
|
|
|
|
|
|
|
|
test fifth::test::basics ... ok
|
|
|
|
|
|
|
|
test fifth::test::iter ... ok
|
|
|
|
|
|
|
|
test fifth::test::iter_mut ... ok
|
|
|
|
|
|
|
|
test fourth::test::into_iter ... ok
|
|
|
|
|
|
|
|
test fourth::test::basics ... ok
|
|
|
|
|
|
|
|
test fourth::test::peek ... ok
|
|
|
|
|
|
|
|
test first::test::basics ... ok
|
|
|
|
|
|
|
|
test second::test::into_iter ... ok
|
|
|
|
|
|
|
|
test second::test::basics ... ok
|
|
|
|
|
|
|
|
test second::test::iter ... ok
|
|
|
|
|
|
|
|
test second::test::iter_mut ... ok
|
|
|
|
|
|
|
|
test third::test::basics ... ok
|
|
|
|
|
|
|
|
test third::test::iter ... ok
|
|
|
|
|
|
|
|
test second::test::peek ... ok
|
|
|
|
|
|
|
|
test silly1::test::walk_aboot ... ok
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
上上下下,左左右右,BABA,哦耶,这个链表无敌了!
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
以上是一个非常典型的<ruby>手指型数据结构<rt>finger data structure</rt></ruby>,在其中维护一个手指,然后操作所需的时间与手指的距离成正比。
|
|
|
|
|
|
|
|
|
|
|
|