{//self.head = node.next;//self.size -= 1;//Some(node.value)//},//None => None,// }//由于。如何理解 rust 的单向链表( 三 )。" />

如何理解 rust 的单向链表( 三 )

{if self.size == 0 {panic!("no value to pop.")}// 使用match匹配// match self.head.take() {//Some(node) => {//self.head = node.next;//self.size -= 1;//Some(node.value)//},//None => None,// }//由于self.size == 0的情况已经考虑 , 因此就不需要match或if let的模式匹配 ,直接letlet node = self.head.take().unwrap();self.head = node.next;self.size -= 1;Some(node.value)}fn peek(&self) -> Option<&i32> {if self.size == 0 {return None;}// map可以从一个Option中取到里面的数据 , 然后操作后再返回给Option进行包装// 就是他描述的:Maps an Option to Option by applying a function to a contained value.self.head.as_ref().map(|node| {&node.value})}fn peek_by_unwrap(&self) -> Option<&i32> {if self.size == 0 {return None;}// 这种方法比较直接 , 先用unwrap打开Option,获取值value后 , 再用Some包起来 , 一样return Some(&self.head.as_ref().unwrap().value);}// 可取出并改值fn peek_mut(&mut self) -> Option<&mut i32> {if self.size == 0 {return None;}self.head.as_mut().map(|node| {&mut node.value})}fn peek_and_update(&mut self, new_value: i32) {if self.size == 0 {return ();}self.head.as_mut().map(|node| {node.value = http://www.kingceram.com/post/new_value;});}}// 这是从rust圣经看到的 , 然后把replace换成takeimpl Drop for List {fn drop(&mut self) {let mut cur_node = self.head.take();while let Some(mut temp_node) = cur_node {println!("---> dropping node --->");cur_node = temp_node.next.take();// temp_node 在这里超出作用域并被 drop,// 由于它的 `next` 字段拥有的 `Node` 被设置为 None,// 因此这里并不会有无边界的递归发生}}}#[cfg(test)]mod test {use super::*;#[test]fn basics() {let mut list = List::new();// Populate listlist.push(1);list.show();list.push(2);list.show();list.push(3);list.show();// Check normal removalassert_eq!(list.pop(), Some(3));assert_eq!(list.pop(), Some(2));list.show();}#[test]fn peek() {let mut list = List::new();assert_eq!(list.peek(), None);assert_eq!(list.peek_mut(), None);list.push(1);list.push(2);list.push(3);assert_eq!(list.peek(), Some(&3));assert_eq!(list.peek_mut(), Some(&mut 3));list.peek_and_update(4);assert_eq!(list.peek(), Some(&4));list.peek_mut().map(|value| {*value = http://www.kingceram.com/post/42});assert_eq!(list.peek(), Some(&42));assert_eq!(list.pop(), Some(42));}}
此时真正的遍历查询所有节点的功能还没有
改进: 接下来就是将原来的i32换成泛型T
type Next = Option>;#[derive(Debug)]struct List {size: u32,head: Next,}#[derive(Debug, PartialEq)]struct Node {value: T,next: Next,}impl List {fn new() -> Self {List {size: 0,// 给头添加一个空元素 , 空元素里面是没值的 , 这样就有一个头了head: None,}}fn push(&mut self, value: T) {// 创建node对象 , 需要了解的是 , 当插入的时候 , 需要将这个节点的下一个元素指向原来List的头 , 这样才是在头部插入// Option.take()的方法描述的很清楚 , 取出Option中的Some(?) , 然后把原来的对象设置为Nonelet new_node = Box::new(Node { value, next: self.head.take() });self.head = Some(new_node);// 此时是添加操作 , 因此元素长度+1self.size += 1;}fn pop(&mut self) -> Option {if self.size == 0 {panic!("no value to pop.")}//由于self.size == 0的情况已经考虑 , 因此就不需要match或if let的模式匹配 ,直接letlet node = self.head.take().unwrap();self.head = node.next;self.size -= 1;Some(node.value)}fn peek(&self) -> Option<&T> {if self.size == 0 {return None;}// map可以从一个Option中取到里面的数据 , 然后操作后再返回给Option进行包装// 就是他描述的:Maps an Option to Option by applying a function to a contained value.self.head.as_ref().map(|node| {&node.value})}fn peek_by_unwrap(&self) -> Option<&T> {if self.size == 0 {return None;}// 这种方法比较直接 , 先用unwrap打开Option,获取值value后 , 再用Some包起来 , 一样return Some(&self.head.as_ref().unwrap().value);}// 可取出并改值fn peek_mut(&mut self) -> Option