【C++之queue的应用及模拟实现】

C++学习笔记---014

  • C++之queue的应用及模拟实现
    • 1、queue的简单介绍
    • 2、queue的简单接口应用
    • 3、queue的模拟实现
      • 3.1、queue的结构一般的构建
      • 3.2、queue的适配器模式构建
      • 3.3、queue的主要接口函数
    • 4、queue的模拟实现完整代码
      • 4.1、一般方式
      • 4.2、泛型模式
    • 5、queue巩固练习题
      • 5.1、最小栈
      • 5.2、栈的匹配(栈的压入和弹出序列)
      • 5.3、逆波兰表达式求值 (后缀表达式)
      • 5.4、两个栈实现队列

C++之queue的应用及模拟实现

前言:
前面篇章学习了C++对于stack容器的基本使用以及常用接口的认识,接下来继续学习,C++的queue的模拟实现等知识。
/知识点汇总/

1、queue的简单介绍

在C++中,queue是一种基于先进先出(FIFO)原则操作的容器。

与日常生活中的排队类似,队列的头部是第一个被添加的元素,也是第一个可以被删除的元素。
新添加的元素总是被放在队列的尾部。
queue为这种数据结构提供了一组函数来操作和访问元素。

以下是queue的一些基本特性和操作

1.基本特性

先进先出(FIFO):队列的头部是第一个被添加的元素,也是第一个可以被删除的元素。新添加的元素总是被放在队列的尾部。
动态性:queue的大小是动态的,可以根据需要自动增长或缩小。
不支持随机访问:queue不支持通过索引直接访问任意位置的元素,只能从队头开始依次访问。
容器的通用性:queue可以容纳任何类型的元素,包括基本类型和自定义类型。

2.常用操作

front():返回queue中第一个元素的引用。如果queue是常量,就返回一个常引用;如果queue为空,返回值是未定义的。
back():返回queue中最后一个元素的引用。如果queue是常量,就返回一个常引用;如果queue为空,返回值是未定义的。
push(const T& obj):在queue的尾部添加一个元素的副本。这是通过调用底层容器的成员函数push_back()来完成的。
push(T&& obj):以移动的方式在queue的尾部添加元素。这是通过调用底层容器的具有右值引用参数的成员函数push_back()来完成的。
pop():移除queue头部的元素。注意,这个操作不返回被移除的元素,也不检查queue是否为空。在调用pop()之前,应确保queue不为空,否则可能会导致未定义行为。
empty():检查queue是否为空。如果为空,返回true;否则返回false。
size():返回queue中元素的数量。

3.需要注意的是:

queue的内部实现使用了底层容器来存储元素,并且只能通过特定的函数来访问和操作元素。默认情况下(官方),底层容器的类型是deque,但也可以使用其他容器类型,如list。
在这里插入图片描述

总的来说,C++中的queue是一个简单但非常实用的数据结构,用于处理那些需要按照特定顺序(即先进先出)访问和操作元素的场景。

2、queue的简单接口应用

void test_queue()
{queue<int> qt;qt.push(1);qt.push(2);qt.push(3);qt.push(4);qt.push(5);while (!qt.empty()){cout << qt.front() << " ";qt.pop();}cout << endl;
}

在这里插入图片描述

3、queue的模拟实现

3.1、queue的结构一般的构建

一般方法的构建:

template<class T>
class queue {
private:T* elements; // 存储元素的数组  int front;   // 队列头部的索引  int rear;    // 队列尾部的下一个位置索引  int capacity; // 队列的容量  
};

3.2、queue的适配器模式构建

template<class T, class Container = list<T>>
class queue
{
private:Container _con;
};

3.3、queue的主要接口函数

void push(const T& x)
{_con.push_back(x);
}
void pop()
{_con.pop_front();
}
T& back()
{return _con.back();
}
const T& back() const
{return _con.back();
}
T& front()
{return _con.front();
}
const T& front() const
{return _con.front();
}
size_t size() const
{return _con.size();
}
bool empty() const
{return _con.empty();
}

4、queue的模拟实现完整代码

4.1、一般方式

#include <iostream>  
#include <stdexcept> // 用于抛出异常  template<class T>
class queue {
private:T* elements; // 存储元素的数组  int front;   // 队列头部的索引  int rear;    // 队列尾部的下一个位置索引  int capacity; // 队列的容量  
public:// 构造函数  queue(int c) {capacity = c;elements = new T[capacity];front = 0;rear = 0;}// 析构函数  ~queue() {delete[] elements;}// 检查队列是否为空  bool isEmpty() const {return front == rear;}// 检查队列是否已满  bool isFull() const {return (rear + 1) % capacity == front;}// 入队操作  void enqueue(const T& value) {if (isFull()) {throw std::out_of_range("Queue is full");}elements[rear] = value;rear = (rear + 1) % capacity;}// 出队操作  void dequeue() {if (isEmpty()) {throw std::out_of_range("Queue is empty");}front = (front + 1) % capacity;}// 访问队首元素  T& frontElement() {if (isEmpty()) {throw std::out_of_range("Queue is empty");}return elements[front];}// 获取队列大小  int size() const {return (rear - front + capacity) % capacity;}
};
// 使用示例  
int main()
{queue<int> q(5); // 创建一个容量为5的int类型队列  q.enqueue(1);q.enqueue(2);q.enqueue(3);std::cout << "Front element: " << q.frontElement() << std::endl;q.dequeue();std::cout << "New front element: " << q.frontElement() << std::endl;std::cout << "Queue size: " << q.size() << std::endl;return 0;
}

4.2、泛型模式

namespace bit
{template<class T, class Container = list<T>>class queue{public:void push(const T& x){_con.push_back(x);}void pop(){_con.pop_front();}T& back(){return _con.back();}const T& back() const{return _con.back();}T& front(){return _con.front();}const T& front() const{return _con.front();}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};
}

5、queue巩固练习题

5.1、最小栈

最小栈:在常数级时间内检索最小元素的栈
思路

两个栈,一个存放原始数据,一个存放当前最小值(不断更新栈顶元素min)

class MinStack 
{
public:MinStack(){}//两个情况进值://1.最开始空栈//2.更新栈顶min小值void push(int val){_st.push(val);if (_minst.empty() || val <= _minst.top()){_minst.push(val);}}void pop(){if (_minst.top() == _st.top()){_minst.pop();}_st.pop();}int top(){return _st.top();}int getMin(){return _minst.top();}stack<int> _st;stack<int> _minst;
};
int main()
{MinStack st;st.push(2);st.push(1);st.push(3);st.push(4);st.push(0);st.pop();cout << st.top() << endl;cout << st.getMin() << endl;return 0;
}

在这里插入图片描述

5.2、栈的匹配(栈的压入和弹出序列)

满足栈的压入与出栈序列合理。
意思就是出栈序列,可满足栈的入栈序列,即”先进后出“。
思路

1.先把入栈序列入栈
2.栈顶元素和出栈序列是否匹配
a、如果匹配就持续出数据,直到栈为空为止
b、如果不匹配,继续入栈
3.结束标志:a、入栈序列走完了 b、栈走完了,也不匹配,不合法的序列

class Solution
{
public:bool IsPopOrder(vector<int>& pushV, vector<int>& popV){int pushi = 0, popi = 0;stack<int> st;while (pushi < pushV.size()){st.push(pushV[pushi++]);while (!st.empty() && st.top() == popV[popi]){++popi;st.pop();}}return st.empty();}
};int main()
{Solution sol;vector<int> pushV = { 1, 2, 3, 4, 5 };//vector<int> popV = { 5, 4, 3, 2, 1 };vector<int> popV = { 4, 5, 3, 2, 1 };//vector<int> popV = { 4, 3, 5, 1, 2 };// 检查出栈序列是否是可能的  bool isPossiblePopOrder = sol.IsPopOrder(pushV, popV);// 打印结果  cout << "Is the pop order possible? " << (isPossiblePopOrder ? "Yes" : "No") << endl;return 0;
}

在这里插入图片描述

5.3、逆波兰表达式求值 (后缀表达式)

操作数在操作符之后的表达式,比如:abcd-*+ — 遇见运算符就开始计算
思路:

利用栈,栈处理操作数和运算符的顺序关系优先级,遇到操作数就入栈,遇到操作数就出栈操作数,运算结果继续入栈,再继续下一个操作数。

class Solution
{
public:int evalRPN(vector<string>& tokens){stack<int> st;//写法2:setset<string> s = { "+","-","*","/" };for (auto& str : tokens){//1.操作数入栈,遇到运算符运算//写法1:穷举//if (str == "+" || "-" == str || "*" == str || "/" == str)//写法2:set -- 容器,搜索树if(s.find(str) != s.end()){//是操作符,根据栈的性质//先取的是右操作数,再是左操作数int right = st.top();st.pop();int left = st.top();st.pop();//运算后的结果入栈switch (str[0])//str[0] --- char整型与case参数匹配{case '+':st.push(left + right);//操作数顺序还原break;case '-':st.push(left - right);break;case '*':st.push(left * right);break;case '/':st.push(left / right);break;}}else{st.push(stoi(str));}}return st.top();}
};
int main()
{Solution sol;// 逆波兰表示法的表达式  vector<string> tokens = { "2", "1", "+", "3", "*" };// 计算表达式的值  int result = sol.evalRPN(tokens);// 打印结果  cout << "The result of the expression is: " << result << endl;return 0;
}

在这里插入图片描述

5.4、两个栈实现队列

实现用两个栈模拟实现队列的”先进先出“。
思路

利用两个栈相互倒,从而满足队列的性质
即:一个push栈进数据,push栈倒数据到一个pop栈,让pop栈出数据。

class MyQueue {
public:MyQueue(){}void push(int x){_pushst.push(x);}int pop(){int retpop = peek();_popst.pop();return retpop;}int peek(){if (_popst.empty()){//倒数据while (!_pushst.empty()){_popst.push(_pushst.top());_pushst.pop();}}return _popst.top();}bool empty(){return _pushst.empty() && _popst.empty();}
private:stack<int> _pushst;stack<int> _popst;
};int main()
{MyQueue qt;qt.push(1);qt.push(2);qt.push(3);qt.push(4);qt.push(5);while (!qt.empty()){printf("%d ", qt.peek());qt.pop();}return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python——详细解析目标检测xml格式标注转换为txt格式

本文简述了目标检测xml格式标注的内容&#xff0c;以及yolo系列模型所需的txt格式标注的内容。并提供了一个简单的&#xff0c;可以将xml格式标注文件转换为txt格式标注文件的python脚本。 1. xml格式文件内容 <size>标签下为图片信息&#xff0c;包括 <width> …

学习ArkTS -- 常用组件使用

学习ArkTS 使用Deveco studio写ArkTSImage: 图片显示组件1.声明Image组件并设置图片源2. 添加图片属性 Text: 文本显示组件1. 声明Text组件并设置文本内容2. 添加文本属性 TextInput&#xff1a;文本输入框1. 声明TextInput2. 添加属性和事件 Button 组件1. 声明Button组件&…

Testng测试框架(2)-测试用例@Test

测试方法用 Test 进行注释&#xff0c;将类或方法标记为测试的一部分。 Test() public void aFastTest() {System.out.println("Fast test"); }import org.testng.annotations.Test;public class TestExample {Test(description "测试用例1")public void…

Arthas排查工具

简介 | arthas (aliyun.com) 在线安装 #下载jar包 curl -O https://arthas.aliyun.com/arthas-boot.jar#启动会先检测虚拟机进程&#xff0c;如果没有启动失败(idea) java -jar arthas-boot.jar linux安装与window一样 卸载arthas rm -rf ~/.arthas/ rm -rf ~/logs/arthas

Unity TextMeshProUGUI 获取文本尺寸·大小

一般使用ContentSizeFitter组件自动变更大小 API 渲染前 Vector2 GetPreferredValues(string text)Vector2 GetPreferredValues(string text, float width, float height)Vector2 GetPreferredValues(float width, float height) 渲染后 Vector2 GetRenderedValues()Vector…

【Linux】网络基础(一)

文章目录 一、计算机网络背景1. 网络发展2. 认识“协议” 二、网络协议初识1. 协议分层2. OSI七层模型3. TCP/IP五层&#xff08;或四层&#xff09;模型 三、网络传输基本流程1. 同局域网的两台主机通信数据包封装和分用封装分用 2. 跨网络的两台主机通信 四、网络中的地址管理…

Rockchip Android13 Vold(一):Native层

一:概述 Vold全称Volume Daemon是用于管理存储类设备的守护进程,负责接收驱动层设备挂载和卸载消息以及与Framework层之间的通信。Vold作为一个守护进程位于Android的Native Daemons层。 二:Vold框架图 三:Vold Sevice Android13的init.rc位于/system/etc/init/hw/其中使…

C语言 | Leetcode C语言题解之第24题两两交换链表中的节点

题目&#xff1a; 题解&#xff1a; struct ListNode* swapPairs(struct ListNode* head) {struct ListNode dummyHead;dummyHead.next head;struct ListNode* temp &dummyHead;while (temp->next ! NULL && temp->next->next ! NULL) {struct ListNod…

【Linux】编写并运行Shell脚本程序操作实例

关于Shell脚本的介绍&#xff1a; Shell脚本是一种用于自动化任务和简化常见操作的脚本语言&#xff0c;通常用于Linux和Unix环境中。Shell脚本允许用户通过编写一系列命令和逻辑语句来执行一系列任务&#xff0c;从而提高了工作效率和自动化水平。 以下是关于Shell脚本的详细…

PlanUML和Mermaid哪个好?

引言 在当今信息化快速发展的时代&#xff0c;数据可视化和图表工具不仅对于程序员&#xff0c;也对于非技术背景的人士至关重要。绘图工具可以帮助我们更好地理解和表达复杂的概念或数据流。PlantUML和Mermaid是两款被广泛使用的绘图语言&#xff0c;它们都能够通过简洁的文本…

测试用例的编写评审

1、什么叫软件测试用例 什么是测试用例 测试用例(TestCase) 是为项目需求而编制的一组测试输入、执行条件 以及预期结果&#xff0c;以便测试某个程序是否满足客户需求。–测试依据 可以总结为:每一个测试点的数据设计和步骤设计。–测试用例 2、测试用例的重要性(了解) 2.1…

航芯通用MCU技术常见问题 | F4专题

日常工作中&#xff0c;我们的销售或技术工程师经常会收到来自用户的问题&#xff0c;其中一些问题是比较常见的&#xff0c;所以为满足日常用户对航芯产品使用及服务的了解&#xff0c;航芯特此推出“通用MCU技术常见问题”专题&#xff0c;分为F0专题及F4专题&#xff0c;欢迎…

Missing artifact org.opencv:opencv:jar:4.10.0 [opencv-4.10.0.jar]

Missing artifact org.opencv:opencv:jar:4.10.0 [opencv-4.10.0.jar] https://mvnrepository.com/artifact/org.opencv/opencv 根本就没有 找了个旧项目的opencv-410.jar修改下opencv-4.10.0.jar放到目录下面就好了 D:\localRepository\org\opencv\opencv\4.10.0 OpenCV-C…

什么是态势感知?

什么是态势感知&#xff1f; 同学&#xff0c;听说过态势感知吗&#xff1f;啥&#xff1f;不知道&#xff1f;不知道很正常&#xff0c;因为态势感知是一个比较小众、比较神秘的概念。为什么态势感知很神秘&#xff0c;首先是因为这是来自军事情报领域的概念&#xff0c;然后…

python--递归算法篇

1、给定一个包含n1个整数的数组nums&#xff0c;其数字在1到n之间&#xff08;包含1和n&#xff09;&#xff0c; 可知至少存在一个重复的整数&#xff0c;假设只有一个重复的整数&#xff0c;请找出这个重复的数 def repeat(ls:list) -> list:#把个数超过1的数&#xff0c…

使用clickhouse-backup备份和恢复数据

作者&#xff1a;俊达 介绍 clickhouse-backup是altinity提供的一个clickhouse数据库备份和恢复的工具&#xff0c;开源项目地址&#xff1a;https://github.com/Altinity/clickhouse-backup 功能上能满足日常数据库备份恢复的需求&#xff1a; 支持单表/全库备份支持备份上…

【opencv】示例-grabcut.cpp 使用OpenCV库的GrabCut算法进行图像分割

left mouse button - set rectangle SHIFTleft mouse button - set GC_FGD pixels CTRLleft mouse button - set GC_BGD pixels 这段代码是一个使用OpenCV库的GrabCut算法进行图像分割的C程序。它允许用户通过交互式方式选择图像中的一个区域&#xff0c;并利用GrabCut算法尝试…

Tomcat无法成功启动——双击startup.bat闪退的解决办法

一、首先查看端口是否被占用了&#xff0c;一般Tomcat的默认端口是8080&#xff0c;可以在管理员命令行通过“netstat -ano|findstr "8080”"的命令查看当前是否有进程占用了端口。 1.如果端口占用了&#xff1a; 则根据PID&#xff08;进程id号&#xff09;来查这个…

深入理解Apache ZooKeeper与Kafka的协同工作原理

目录 引言 一、ZooKeeper基础概念 &#xff08;一&#xff09;ZooKeeper简介 &#xff08;二&#xff09;ZooKeeper数据结构 &#xff08;三&#xff09;ZooKeeper特点 &#xff08;四&#xff09;应用场景 二、ZooKeeper工作模式 &#xff08;一&#xff09;工作机制 …

jeecg-boot安装

我看大家都挺关注&#xff0c;所以集中上传了下代码和相关工具&#xff0c;方便大家快速完成 链接&#xff1a;https://pan.baidu.com/s/1-Y9yHVZ-4DQFDjPBWUk4-A 提取码&#xff1a;op1r 1. 下载代码 下载地址 : JEECG官方网站 - 基于BPM的低代码开发平台(低代码平台_零代…