数据结构与算法-Rust 版读书笔记-2线性数据结构-队列

news2024/11/18 3:41:30

数据结构与算法-Rust 版读书笔记-2线性数据结构-队列

1、队列:先进先出

队列是项的有序集合,其中,添加新项的一端称为队尾,移除项的另一端称为队首。一个元素在从队尾进入队列后,就会一直向队首移动,直到它成为下一个需要移除的元素为止。

2、Rust 预备知识

1、Some

rust为了处理情况设置的两个枚举类型,分别是enum Option 和enum Result。

Option的枚举情况有两种,分别是代表有的Some()和代表无的None。 如果是有返回值,则可以通过if let,match,unwrap,?等多种方法对应情况取出Some包裹的值,如果没有则是None。

Result的枚举情况也是有两种,表示正确的Ok()和表示错误的Err()。同样也是match,unwrap等等对应方法去提取。分别提取对应情况的内容。

3、队列的 Rust 代码实现、运行结果

queue.rs

/*
 * @Description: 
 * @Author: tianyw
 * @Date: 2023-12-10 17:43:34
 * @LastEditTime: 2023-12-11 21:46:30
 * @LastEditors: tianyw
 */
// 定义队列
#[derive(Debug)] // Debug 是派生宏的名称,此语句为 Queue 结构体实现了 Debug trait

pub struct Queue<T> { // pub 表示公开的
    cap: usize, // 容量
    data: Vec<T>, // 数据容器
}

impl<T> Queue<T> { // impl 用于定义类型的实现,如实现 new 方法、is_empty 方法等
    // 初始化空栈
    pub fn new(size: usize) -> Self { // 指代 Queue 类型
        Self {
           cap: size,
           data:Vec::with_capacity(size)
        }
    }

    pub fn is_empty(&self) -> bool {
        0 == Self::len(&self)
    }

    pub fn is_full(&self) -> bool {
        self.len() == self.cap
    }

    pub fn len(&self) -> usize { // &self 只可读
        self.data.len()
    }

    // 清空
    pub fn clear(&mut self) { // &mut self 可读、可写
        self.data = Vec::with_capacity(self.cap)
    }

    // 判断是否有剩余空间,如果有的话,就将数据添加到队列中
   pub fn enquue(&mut self, val: T) -> Result<(), String> {
    if self.len() == self.cap {
        return  Err("No space available".to_string());
    }
    self.data.insert(0, val);
    Ok(())
   }

   // 数据出队
   pub fn dequeue(&mut self) -> Option<T> {
    if self.len() > 0 {
        self.data.pop()
    }else {
        None
    }
   }

    // 以下是为队列实现的迭代功能
    // into_iter:队列改变,成为迭代器
    // iter: 队列不变,得到不可变迭代器
    // iter_mut: 队列不变,得到可变迭代器
    pub fn into_iter(self) -> IntoIter<T> {
        IntoIter(self)
    }

    pub fn iter(&self) -> Iter<T> {
        let mut iterator = Iter { stack: Vec::new() };
        for item in self.data.iter() {
            iterator.stack.push(item);
        }
        iterator
    }

    pub fn iter_mut(&mut self) -> IterMut<T> {
        let mut iterator = IterMut { stack: Vec::new() };
        for item in self.data.iter_mut() {
            iterator.stack.push(item);
        }
        iterator
    }

    
}

// 实现三种迭代功能
pub struct IntoIter<T>(Queue<T>);
impl<T:Clone> Iterator for IntoIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if !self.0.is_empty() {
            Some(self.0.data.remove(0))
        } else {
            None
        }
    }
}

pub struct Iter<'a,T:'a> { stack: Vec<&'a T>, }
impl<'a,T> Iterator for Iter<'a,T> {
    type Item = &'a T;
    fn next(&mut self) -> Option<Self::Item> {
        if 0 != self.stack.len() {
            Some(self.stack.remove(0)) // 索引移除
        }else {
            None
        }
    }
}

pub struct IterMut<'a,T:'a> { stack: Vec<&'a mut T> }
impl<'a,T> Iterator for IterMut<'a,T> {
    type Item = &'a mut T;
    fn next(&mut self) -> Option<Self::Item> {
       if 0 != self.stack.len() {
        Some(self.stack.remove(0))
       }else {
        None
       }
    }
}    


main.rs

/*
 * @Description: 
 * @Author: tianyw
 * @Date: 2023-12-11 21:29:04
 * @LastEditTime: 2023-12-11 21:54:22
 * @LastEditors: tianyw
 */

mod queue;
fn main() {
    basic();
    iter();

    fn basic() {
        let mut q = queue::Queue::new(4);
        let _r1 = q.enquue(1);
        let _r2 = q.enquue(2);
        let _r3 = q.enquue(3);
        let _r4 = q.enquue(4); // 入队

        if let Err(error) = q.enquue(5) {
            println!("Enqueue error:{error}")
        }

        if let Some(data) = q.dequeue() { // 出队
            println!("dequeue data: {data}");
        }else {
            println!("empty queue");
        }

        println!("empty: {}, len: {}", q.is_empty(),q.len());
        println!("full: {}",q.is_full());
        println!("q: {:?}",q);
        q.clear();
        println!("{:?}",q);
    }


    fn iter() {
        let mut q = queue::Queue::new(4);
        let _r1 = q.enquue(1);
        let _r2 = q.enquue(2);
        let _r3 = q.enquue(3);
        let _r4 = q.enquue(4);

        let sum1 = q.iter().sum::<i32>();
        let mut addend = 0;
        for item in q.iter_mut() {
            *item += 1;
            addend += 1;
        }
        let sum2 = q.iter().sum::<i32>(); // vec 的 sum 方法
        println!("{sum1} + {addend} = {sum2}");
        println!("sum = {}",q.into_iter().sum::<i32>())
    }
}

cargo run 运行结果

在这里插入图片描述

队列的典型应用是模拟以FIFO方式管理数据的真实场景。

应用:烫手山芋游戏

// hot_potato.rs
 
fn hot_potato(names: Vec<&str>, num: usize) -> &str {
    // 初始化队列,将人名入队
    let mut q = Queue::new(names.len());
    for name in names { let _nm = q.enqueue(name); }
 
    while q.size() > 1 {
        // 出入栈中的人名,相当于传递山芋
        for _i in 0..num {
            let name = q.dequeue().unwrap();
            let _rm = q.enqueue(name);
        }
 
        // 出入栈达到num次,删除一个人名
        let _rm = q.dequeue();
    }
 
    q.dequeue().unwrap()
}
 
fn main() {
    let name = vec!["Mon","Tom","Kew","Lisa","Marry","Bob"];
    let survivor = hot_potato(name, 8);
    println!("The survival person is {survivor}");
    // 输出“The survival person is Marry”
}

注意,在上面的实现中,计数值8大于队列中的人名数量6。但这不存在问题,因为队列就像一个圈,到了队尾就会重新回到队首,直至达到计数值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1303025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

财务机器人(RPA)会影响会计人员从业吗?

财务机器人会对会计从业人员有影响。 不过是正面积极的影响。 它是财务人员工作的好助手好帮手。 具体展开聊聊财务RPA机器人是如何成为财务人员的好帮手。 财务机器人是在人工智能和自动化技术的基础上建立的、以软件机器人作为虚拟劳动力、依据预先设定的程序与现有用户系…

Axure的安装以及简单使用

目录 Axure简介 是什么 有什么用 Axure的优缺点 优点&#xff1a; 缺点&#xff1a; 安装 汉化 Axure的使用 工具栏 页面 ​编辑 添加子页面 ​编辑 Axure简介 是什么 Axure是一款著名的原型设计工具。它允许用户创建交互式线框图、流程图、原型和其他设计文档&…

ERROR: [BD 41-237] Bus Interface property FREQ_HZ does not match between

在自定义IP出现以上错误时可以通过双击模块clk属性 如果是灰色无法二次编辑时&#xff0c;在封装IP时&#xff0c;选择以下菜单

【笔记】硬件工程师入门基础课程

学习视频&#xff08;b站&#xff09;&#xff1a;硬件工程师入门基础元器件课程 基础元器件课程 p1 电阻1. 定义、特性及参数1.1 色环电阻 识别方法&#xff1a;1.2 伏安特性1.3 基本参数 2.电阻的功能2.1 分压2.2 限流2.3 浪涌保护 3. 如何选择电阻 p2 电容1. 电容的定义1.1电…

redis(设置密码)配置文件详细

1.设置账号密码端口 config set requirepass 123456 设置密码为123456 config get requirepass 查看账号密码 auth 123456 登入的时候输入这个确定账号密码 1. 首先连接到Redis服务器: redis-cli 2. 然后使用CONFIG SET命令设置requirepass参数并指定密码: CONFIG SET requi…

Viewport Meta 标记:让网页适应各种设备的魔法符号

在我们用手机或平板电脑浏览网页时&#xff0c;你是否曾发现有些网页能够很好地适应屏幕&#xff0c;而有些却需要左右滑动才能完整显示内容&#xff1f;这就涉及到一个神奇的东西——Viewport Meta 标记。 最近本人在研究自适应的各自实现方法&#xff0c;比如media媒体查询、…

PR快闪模板|简约时尚快节奏开场视频PR模板剪辑素材

这是一款Premiere Pro快闪模板&#xff0c;简约时尚快节奏开场视频 pr模板剪辑素材&#xff0c;用于以独创的方式创建明亮的介绍、时尚的开场白或模特展示。 Premiere Pro CC21及以上&#xff0c;即使是初学者也可以轻松使用&#xff0c;包含视频教程。 来自PR模板网&#xff1…

Go json 差异比较 json-diff(RFC6902)

Go json 差异比较 json-diff(RFC 6902) 毕业设计中过程中为了比较矢量图的差异而依据 RFC 6902 编写的一个包&#xff0c;现已开源&#xff1a; Json-diff 使用 go get -u github.com/520MianXiangDuiXiang520/json-diff序列化与反序列化 与官方 json 包的序列化和反序列化不…

微服务学习|elasticsearch:数据聚合、自动补全、数据同步

数据聚合 聚合的分类 聚合 (aggregations)可以实现对文档数据的统计、分析、运算。聚合常见的有三类: 桶(Bucket)聚合:用来对文档做分组 TermAggregation:按照文档字段值分组 Date Histogram:按照日期阶梯分组&#xff0c;例如一周为一组&#xff0c;或者一月为一组 度量(M…

动能资讯 | 智慧汽车—城市NOA迎爆发

在特斯拉引领的 TransformerBev 架构驱动下&#xff0c;智驾算法趋近于端到端的智驾大模型&#xff0c;使得智能驾驶开始步入城市 NOA 新时代。 消费者认知增强&#xff0c;未来市场空间广阔。伴随城市 NOA 在 23-24 年的落地和普及、L3 法规在年内的落地&#xff0c;行业 0-1…

Java-异常(一)-异常的概述和常见异常的举例

&#x1f436;b站视频 124-异常处理-异常的概述与常见异常的举例_哔哩哔哩_bilibili 目录 b站视频 5.1 异常概念 5.2 Error 示例代码 5.3 Exception异常划分 ❓面试题&#xff1a;常见的异常有哪些&#xff1f;举例说明 &#x1f436;5.1 异常概念 在使用计算机语言进行…

HarmonyOS应用开发-手写板

这是一个基于HarmonyOS做的一个手写板应用&#xff0c;只需要简单的几十行代码&#xff0c;就可以实现如下手写功能以及清空画布功能。 一、先上效果图&#xff1a; 二、上代码 Entry Component struct Index {//手写路径State pathCommands: string ;build() {Column() {//…

HCIA-H12-811题目解析(10)

1、【单选题】DHCP客户端在租期到达哪个比例时第一次发送续租报文&#xff1f; 2、【单选题】在WLAN中用于标识无线网络&#xff0c; 区分不同的无线网络的是&#xff1f; 3、【单选题】我们在笔记本电脑上搜索可接入无线网络时&#xff0c;显示出来的网络名称实际是 4、【单…

leetcode 904. 水果成篮(优质解法)

代码&#xff1a; class Solution {public int totalFruit(int[] fruits) {int lengthfruits.length;int []fruitNumsnew int[length1]; //用于记录各个种类摘了多少个水果int count0; //用于记录当前采摘了几种水果int sum0; //用于记录当前共摘了多少水果for(int left0…

mmseg上手自己的数据集

制作自己的数据集&#xff0c;VOC格式为例。 这三个文件包括数据集的名称。可以使用labelme脚本自动生成。 跟据预测类别修改配置文件 D:\projects\mmsegmentation-main\mmseg\datasets\voc.py 因为是voc格式的数据集&#xff0c;在这个文件里进行配置&#xff0c;修改成自己数…

at least 1 bean which qualifies as autowire candidate

No qualifying bean of type com. spdbcccdl.mapper.dl.DatabaseDaoavailable: expected at least 1 bean which qualifies as autowire candidate.

《PySpark大数据分析实战》-02.了解Hadoop

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…

PC 机与单片机通信(RS232 协议)

PC 机与单片机通信(RS232 协议) 目录&#xff1a; 1、单片机串口通信的应用 2、PC控制单片机IO口输出 3、单片机控制实训指导及综合应用实例 4、单片机给计算机发送数据&#xff1a; [实验任务] 单片机串口通信的应用&#xff0c;通过串口&#xff0c;我们的个人电脑和单…

智能优化算法应用:基于阴阳对算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于阴阳对算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于阴阳对算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.阴阳对算法4.实验参数设定5.算法结果6.参考文…

搜集怎么绘制三维曲线和曲面?

1、针对函数对象是单一变量、两个函数的情况。用plot3函数&#xff1b;&#xff08;三维曲线&#xff09; 看一下matlab官方的例子&#xff1a; t 0:pi/50:10*pi; st sin(t); ct cos(t); plot3(st,ct,t) 绘制出来的曲线&#xff1a; 几个比较关键的点&#xff1a; &…