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

news2024/11/18 13:58:31

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

1、双端队列

deque又称为双端队列,双端队列是与队列类似的项的有序集合。deque有两个端部:首端和尾端。deque不同于队列的地方就在于项的添加和删除是不受限制的,既可以从首尾两端添加项,也可以从首尾两端移除项。在某种意义上,这种混合线性结构提供了栈和队列的所有功能。

虽然deque拥有栈和队列的许多特性,但其不需要像它们一样强制地进行LIFO和FIFO排序,这取决于如何添加和删除数据。deque既可以当作栈使用,也可以当作队列使用,但最好不要如此,因为不同的数据结构都有自身的特性,它们均是为了不同的计算目的而设计的。

2、双端队列的 Rust 代码实现、运行结果

queue.rs

/*
 * @Description: 
 * @Author: tianyw
 * @Date: 2023-12-10 17:43:34
 * @LastEditTime: 2023-12-11 22:19:06
 * @LastEditors: tianyw
 */
// 定义队列
#[derive(Debug)]

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

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

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

    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)
    }

    // Vec 的末尾为队首
   pub fn add_front(&mut self, val: T) -> Result<(), String> {
    if self.len() == self.cap {
        return  Err("No space available".to_string());
    }
    self.data.push(val);
    Ok(())
   }

   // Vec 的首部为队尾
   pub fn add_rear(&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 remove_front(&mut self) -> Option<T> {
    if self.len() > 0 {
        self.data.pop()
    }else {
        None
    }
   }

   // 从队尾移除数据
   pub fn remove_rear(&mut self) -> Option<T> {
    if self.len() > 0 {
        Some(self.data.remove(0))
    }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>(Deque<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 22:21:01
 * @LastEditors: tianyw
 */

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

    fn basic() {
        let mut d = deque::Deque::new(4);
        let _r1 = d.add_front(1);
        let _r2 = d.add_front(2);
        let _r3 = d.add_rear(3);
        let _r4 = d.add_rear(4); // 入队

        if let Err(error) = d.add_front(5) {
            println!("Enqueue error:{error}")
        }
        
        println!("{:?}",d);

        match d.remove_rear() {
            Some(data) => println!("remove rear data {data}"),
            None => println!("empty deque"),
        }

        match d.remove_front() {
            Some(data) => println!("remove front data {data}"),
            None => println!("empty deque"),
        }

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

    fn iter() {
        let mut d = deque::Deque::new(4);
        let _r1 = d.add_front(1);
        let _r2 = d.add_front(2);
        let _r3 = d.add_rear(3);
        let _r4 = d.add_rear(4);

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

cargo run 运行结果

在这里插入图片描述

应用:回文检测

// palindrome_checker.rs
 
fn palindrome_checker(pal: &str) -> bool {
    // 数据入队
    let mut d = Deque::new(pal.len());
    for c in pal.chars() {
        let _r = d.add_rear(c);
    }
 
    let mut is_pal = true;
    while d.size() > 1 && is_pal {
        // 出队首尾字符
        let head = d.remove_front();
        let tail = d.remove_rear();
 
        // 比较首尾字符,若不同,则字符串非回文
        if head != tail {
            is_pal = false;
        }
    }
 
    is_pal
}
 
fn main() {
    let pal = "rustsur";
    let is_pal = palindrome_checker(pal);
    println!("{pal} is palindrome string: {is_pal}");
    // 输出“rustsur is palindrome string: true”
 
    let pal = "panda";
    let is_pal = palindrome_checker(pal);
    println!("{pal} is palindrome string: {is_pal}");
    // 输出“panda is palindrome string: false”
}

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

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

相关文章

记一次测试环境git翻车经历

本来想拉一个功能分支进行新的功能开发&#xff0c;合并代码发现没有冲突居然有文件被修改了&#xff0c;贸然选择最近的一次回滚提交&#xff0c;没想到不假思索的push -f 导致一部分dev主干的代码不见了。 事故记录 开发分支origin/dev&#xff0c;功能分支file 合并之后发…

金额格式化,利率格式化

<el-inputplaceholder"请输入"size"medium"v-model"amt"maxlength"16":disabled"showBtn no || readOnly"oninput"this.value this.value.replace(/[^\d.]/g,).replace(/\.{2,}/g, .).replace(/^0(\d)/, $1) // 第…

Android--Jetpack--Databinding源码解析

慢品人间烟火色&#xff0c;闲观万事岁月长 一&#xff0c;基本使用 关于databinding的基本使用请看之前的文章 Android--Jetpack--Databinding详解-CSDN博客 二&#xff0c;xml布局解析 分析源码呢&#xff0c;主要就是从两方面入手&#xff0c;一个是使用&#xff0c;一个…

Nginx正则表达式

目录 1.nginx常用的正则表达式 2.location location 大致可以分为三类 location 常用的匹配规则 location 优先级 location 示例说明 优先级总结 3.rewrite rewrite功能 rewrite跳转实现 rewrite执行顺序 语法格式 rewrite示例 实例1&#xff1a; 实例2&#xf…

Vue3封装一个轮播图组件

先看效果 编写组件代码 CarouselChart.vue <template><div classimg-box><el-button clickpreviousImages v-ifprops.showBtn>←</el-button><div classimg><div styledisplay: flex;gap: 20px idmove><imgclassimg-item v-for(item…

hdlbits系列verilog解答(Ringer)-55

文章目录 一、问题描述二、verilog源码三、仿真结果 一、问题描述 本次我们设计一个电路以实现对手机铃声和振动的控制。当工作在振动模式时&#xff0c;开启振动&#xff0c;否则开启铃声。 尝试只使用assign语句&#xff0c;测试一下你是否能将描述转化成数字逻辑电路。 二…

Guava反射工具详解

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;今天咱们聊聊Java反射&#xff0c;特别是在Guava这个强大的库中&#xff0c;它是怎么让反射变得更简单&#xff0c;更有趣的。咱们都知道&#xff0c;反射在Java中是个相当强大的特性&#xff0c;它允许程序在运…

基于ssm的校园快递一站式服务系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本校园快递一站式服务系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数…

【Java 基础】30 JDK动态代理

文章目录 1.定义2.原理3.使用1&#xff09;定义业务接口2&#xff09;实现 InvocationHandler 接口3&#xff09;生成代理类 4.优点5.缺点总结 动态代理是一种重要的 设计模式&#xff0c;它允许在运行时生成代理类来代替实际的类。动态代理主要通过反射机制实现&#xff0c;为…

计算机图形学——消隐算法

目录 消隐算法 &#xff08;1&#xff09;隐藏线消除算法 &#xff08;2&#xff09;隐藏面消除算法 曲面体消隐算法 3D Mesh 隐藏面消除算法 &#xff08;1&#xff09;深度缓冲器算法&#xff08;zBuffer&#xff09; 深度缓冲器 &#xff08;2&#xff09;深度排序…

机器学习基础介绍

百度百科&#xff1a; 机器学习是一门多领域交叉学科&#xff0c;涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为&#xff0c;以获取新的知识或技能&#xff0c;重新组织已有的知识结构使之不断改善自身的性能。 …

mysql 链接超时的几个参数详解

mysql5.7版本中&#xff0c;先查看超时设置参数&#xff0c;我们这里只关注需要的超时参数&#xff0c;并不是全都讲解 show variables like %timeout%; connect_timeout 指的是连接过程中握手的超时时间,在5.0.52以后默认为10秒&#xff0c;之前版本默认是5秒&#xff0c;主…

学习人工智能-基础篇

背景 随着大模型的火爆&#xff0c;人工智能再次被推到高潮&#xff0c;其实它在众多行业领域已经落地很多应用&#xff0c;并给社会带来了巨大的经济价值。其中包括互联网、教育、金融、医疗、交通、物流等等。在测试领域也有一些落地的案例&#xff0c;作为测试人员&#xf…

关于个人职业选择

职业选择&#xff0c;一直是个老生常谈的话题。这并不是一个容易做的决定。 让我们来看看AI怎么说。 首先是方向性的回答&#xff1a; 然后是一些具体的回答 我个人比较倾向于深耕网络安全。这是一个很有趣也是一个持续发展着的领域。 不知道关于这个事情你怎么看&#xff0…

案例解决Redis高并发场景带来的缓存穿透、击穿、雪崩问题(超级详细!!)

假设你的网站流量量达到亿级&#xff0c;传统的去查询DB势必会给DB带来巨大的压力&#xff0c;甚至可能有宕机的风险&#xff0c;接下来我就分几个阶段&#xff0c;来讲诉各个场景可能会给DB带来巨大压力的可能&#xff0c;以及优化的方案。 缓存击穿&#xff1a;key对应的数据…

2023年12月11日:ui界面跳转

头文件&#xff1a;Second #ifndef SECOND_H #define SECOND_H#include <QWidget>namespace Ui { class Second; }class Second : public QWidget {Q_OBJECTpublic:explicit Second(QWidget *parent nullptr);~Second(); public slots:void jump_slot(); private:Ui::S…

飞桨星河文心SDK与open interpreter构成“小天网”雏形

飞桨星河文心SDK与open interpreter构成“小天网”雏形 开放式解释器open interpreter是大模型和自然语言交互的神器&#xff0c;本项目旨在体验文心大模型为底座的open interpreter。本项目只需使用CPU环境即可运行&#xff0c;直接运行即可“运行全部Cell”&#xff0c;本项…

访问控制列表ACL学习

ACL概念 ACL: ACL 是 Access Control List&#xff08;访问控制列表&#xff09;的缩写。它是一种用于管理和控制访问权限的机制或数据结构。ACL 用于确定谁可以访问特定资源&#xff08;例如文件、文件夹、网络资源等&#xff09;以及他们可以执行的操作。ACL 通常由一系列访…

【EMNLP 2023】面向Stable Diffusion的自动Prompt工程算法

近日&#xff0c;阿里云人工智能平台PAI与华南理工大学朱金辉教授团队合作在自然语言处理顶级会议EMNLP2023上发表了BeautifulPrompt的深度生成模型&#xff0c;可以从简单的图片描述中生成高质量的提示词&#xff0c;从而使文生图模型能够生成更美观的图像。BeautifulPrompt通…

1、混合方式UI设计

1、混合方式UI设计 新建项目添加静态资源添加资源添加action添加菜单菜单栏工具栏中间编辑区域 代码添加其他组件字体和大小状态栏 添加槽函数UI设置的转到槽的手写的设置应用程序图标 代码 新建项目 MainWindow代码文件夹主窗口为 (QMainWindow) 添加静态资源 AppIcon.icoi…