首页 > 其他分享 >024 通过链表学Rust之非安全方式实现链表2

024 通过链表学Rust之非安全方式实现链表2

时间:2022-11-07 10:37:09浏览次数:52  
标签:mut self list iter next 链表 024 eq 之非


介绍

视频地址:https://www.bilibili.com/video/av78062009/
相关源码:https://github.com/anonymousGiga/Rust-link-list

详细内容

本节实现剩余的迭代器、Drop等。

IntoIter

实现代码如下:

//实现IntoIter
pub struct IntoIter<T> (List<T>);

impl<T> List<T> {
pub fn into_iter(self) -> IntoIter<T> {
IntoIter(self)
}
}

impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop()
}
}

Iter

代码如下:

//实现Iter
pub struct Iter<'a, T> {
next: Option<&'a Node<T>>,
}

impl<T> List<T> {
pub fn iter(&self) -> Iter<T> {
Iter { next: self.head.as_deref() }
}
}

impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.next.map(|node| {
self.next = node.next.as_deref();
&node.elem
})
}
}

IterMut

实现代码如下:

//实现IterMut
pub struct IterMut<'a, T> {
next: Option<&'a mut Node<T>>,
}

impl<T> List<T> {
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut { next: self.head.as_deref_mut() }
}
}

impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.next.take().map(|node| {
self.next = node.next.as_deref_mut();
&mut node.elem
})
}
}

测试代码

#[test]
fn into_iter() {
let mut list = List::new();
list.push(1); list.push(2); list.push(3);

let mut iter = list.into_iter();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), None);
}

#[test]
fn iter() {
let mut list = List::new();
list.push(1); list.push(2); list.push(3);

let mut iter = list.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), None);
}

#[test]
fn iter_mut() {
let mut list = List::new();
list.push(1); list.push(2); list.push(3);

let mut iter = list.iter_mut();
assert_eq!(iter.next(), Some(&mut 1));
assert_eq!(iter.next(), Some(&mut 2));
assert_eq!(iter.next(), Some(&mut 3));
assert_eq!(iter.next(), None);
}

完整代码

use std::ptr;
pub struct List<T> {
head: Link<T>,
tail: *mut Node<T>,
}

type Link<T> = Option<Box<Node<T>>>;

struct Node<T> {
elem: T,
next: Link<T>,
}

impl<T> List<T> {
pub fn new() -> Self {
List { head: None, tail: ptr::null_mut() }
}

pub fn push(&mut self, elem: T) {
let mut new_tail = Box::new(Node {
elem: elem,
next: None,
});

let raw_tail: *mut _ = &mut *new_tail;

if !self.tail.is_null() {
unsafe {
(*self.tail).next = Some(new_tail);
}
} else {
self.head = Some(new_tail);
}

self.tail = raw_tail;
}

pub fn pop(&mut self) -> Option<T> {
self.head.take().map(|head| {
let head = *head;
self.head = head.next;

if self.head.is_none() {
self.tail = ptr::null_mut();
}
head.elem
})
}
}

//实现IntoIter
pub struct IntoIter<T> (List<T>);

impl<T> List<T> {
pub fn into_iter(self) -> IntoIter<T> {
IntoIter(self)
}
}

impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop()
}
}

//实现Iter
pub struct Iter<'a, T> {
next: Option<&'a Node<T>>,
}

impl<T> List<T> {
pub fn iter(&self) -> Iter<T> {
Iter { next: self.head.as_deref() }
}
}

impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
self.next.map(|node| {
self.next = node.next.as_deref();
&node.elem
})
}
}

//实现IterMut
pub struct IterMut<'a, T> {
next: Option<&'a mut Node<T>>,
}

impl<T> List<T> {
pub fn iter_mut(&mut self) -> IterMut<T> {
IterMut { next: self.head.as_deref_mut() }
}
}

impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
self.next.take().map(|node| {
self.next = node.next.as_deref_mut();
&mut node.elem
})
}
}



#[cfg(test)]
mod tests {
use super::List;

#[test]
fn basics() {
let mut list = List::new();
assert_eq!(list.pop(), None);

list.push(1);
list.push(2);
list.push(3);

assert_eq!(list.pop(), Some(1));
assert_eq!(list.pop(), Some(2));
list.push(4);
assert_eq!(list.pop(), Some(3));
assert_eq!(list.pop(), Some(4));
assert_eq!(list.pop(), None);
}

#[test]
fn into_iter() {
let mut list = List::new();
list.push(1); list.push(2); list.push(3);

let mut iter = list.into_iter();
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(3));
assert_eq!(iter.next(), None);
}

#[test]
fn iter() {
let mut list = List::new();
list.push(1); list.push(2); list.push(3);

let mut iter = list.iter();
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), None);
}

#[test]
fn iter_mut() {
let mut list = List::new();
list.push(1); list.push(2); list.push(3);

let mut iter = list.iter_mut();
assert_eq!(iter.next(), Some(&mut 1));
assert_eq!(iter.next(), Some(&mut 2));
assert_eq!(iter.next(), Some(&mut 3));
assert_eq!(iter.next(), None);
}
}


标签:mut,self,list,iter,next,链表,024,eq,之非
From: https://blog.51cto.com/u_15862521/5828075

相关文章

  • 数组、链表
    1.前缀和数组2.差分数组3.滑动窗口算法4.二分搜索5.双指针技巧汇总6.原地修改数组7.单链表的六大解题套路8.链表操作的递归思维......
  • 114. 二叉树展开为链表
    给你二叉树的根结点 root ,请你将它展开为一个单链表:展开后的单链表应该同样使用 TreeNode ,其中 right 子指针指向链表中下一个结点,而左子指针始终为 null 。展......
  • 【随机过程】随机过系列之非平稳过程
    非平稳过程有很多种,这里介绍两种:周期(循环)平稳过程和正交增量过程。说实话这一讲听的迷迷糊糊的,如果后面有新的理解会做补充。周期平稳$R_X(t,s)=R_X(t+T,s+T),\exist......
  • 【1024】程序员节快乐
    今天是10月24日程序员节,蚕豆哥祝所有的程序员节日快乐!(很有幸自己10年前是一名JAVA攻城师,虽然只维持了9个月<_>) 简单水一下程序员节的由来10月24日是中国版的“程序员节......
  • rust 基础 —— 创建链表
    使用枚举类usecrate::List::{Cons,Nil};enumList{//Cons:元组结构体,包含链表的一个元素和一个指向下一节点的指针Cons(u32,Box<List>),//Nil:末结......
  • leetcode 160. 相交链表 js 实现
    给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。图示两个链表在节点 c1 开始相交: ......
  • 算法题--从尾到头打印链表
    5要求时间限制:1秒空间限制:32768K题目描述输入一个链表,从尾到头打印链表每个节点的值解题思路链表必须要从头开始访问,如果需要将打印顺序颠倒,可以利用栈的特性。有时......
  • 双链表实现栈,和队列
    packageclass03;importjava.util.LinkedList;importjava.util.Queue;importjava.util.Stack;/***双链表实现栈,和队列*/publicclassCode03_DoubleEndsQu......
  • 单链表,双链表反转
    packageclass03;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;/***单链表,双链表反转*/publicclassCode01_ReverseLis......
  • 链表的头插法与尾插
    链表是数据结构的一种,多个节点指向形成一个连接在向链表中添加数据时存在两种插入方法:头插法:每插入一个节点,都会代替原来的头部的节点,然后新的头部节点的指针指向......