C++——stack与queue

C++——stack与queue

目录

引言

容器适配器

一、什么是容器适配器

二、底层容器的选择

标准库中的stack

一、stack的基本概念

二、stack的常用接口

三、stack的模拟实现

标准库中的queue

一、queue的基本概念

二、queue的常用接口

三、queue的模拟实现

标准库中的priority_queue

一、priority_queue的基本概念

二、priority_queue的常用接口

三、priority_queue的使用

结束语


引言

在之前的博客中,我们学习了栈(Stack)与队列(Queue)并尝试使用C语言实现其功能,同时我们在C++的学习中对STL中的string vector等容器也进行了学习,接下来我们来学习C++中的栈和队列。

可以先看看这两篇文章,更有助于我们学习:

数据结构——顺序栈和链式栈

数据结构——链式队列和循环队列

容器适配器

在学习stack和queue之前,我们先来了解一下容器适配器。

一、什么是容器适配器

适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结),该种模式是将一个类的接口转换成客户希望的另外一个接口。

我们可以点开下面两个文档来查看一下:

stack文档

queue文档

priority_queue文档

我们可以看到:在stack容器适配器和queue容器适配器默认使用deque作为其底层容器。priority_queue默认使用vector作为底层容器。

二、底层容器的选择

那么为什么stack和deque会默认使用deque作为底层容器呢,priority_queue会使用vector作为底层容器呢?

我们之前学习过deque,我们也清楚deque的作用:deque支持在头尾两端进行高效的插入和删除操作,这与stack和queue的需求一致。相比之下,vector虽然提供高效的随机访问,但其插入和删除操作只在末尾高效;而list则在任何位置插入和删除都高效,但不提供随机访问。因此,deque是兼顾性能和灵活性的最佳选择。

而priority_queue需要随机访问和堆操作,因此它选择vector作为底层容器。虽然deque也支持这些操作,但vector在内存布局和性能优化方面更适合priority_queue的需求。

标准库中的stack

一、stack的基本概念

在之前的学习中我们已经对stack有所了解,它遵循后进先出(Last In First Out,LIFO)的原则。具体来说就就是STL对与栈这个数据结构的封装,使用时需要包含头文件#include<stack>。

二、stack的常用接口

函数说明接口说明
stack()构造空的栈
empty()检测stack是否为空
size()返回stack中的元素个数
top()返回栈顶元素的引用
push()将元素val压入stack中
pop()将stack中尾部的元素弹出

这些接口也十分简单,这里就不过多解释了。直接来看使用实例:

int main() { stack<int> st; st.push(1); st.push(2); st.push(3); st.push(4); st.push(5); cout << "容量大小为:" << st.size() << endl; cout << "出栈顺序为:"; while (!st.empty()) { int top = st.top(); st.pop(); cout << top << " "; } cout << endl; return 0; } 

三、stack的模拟实现

我们接下来可以试着模拟实现stack:

#include<deque> namespace Stack { template<class T, class Con=deque<T>> // template<class T, class Con=vector<T>> // template<class T, class Con = list<T>> class stack { public: stack() { // ... } void push(const T& x) { _c.push_back(x); } void pop() { _c.pop_back(); } T& top() { return _c.back(); } const T& top() const { return _c.back(); } size_t size() const { return _c.size(); } bool empty() const { return _c.empty(); } private: Con _c; }; } 

来个简单的测试代码:

int main() { Stack::stack<int> st; st.push(10); st.push(20); st.push(30); st.push(40); st.push(50); cout << st.top() << endl; cout << st.size() << endl; st.pop(); cout << st.top() << endl; cout << "Is stack empty? " << (st.empty() ? "Yes" : "No") << endl; while (!st.empty()) { st.pop(); } cout << "Is stack empty? " << (st.empty() ? "Yes" : "No") << endl; return 0; }

输出结果如下:

标准库中的queue

一、queue的基本概念

队列是一种线性表,其特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。这种数据结构遵循“先进先出”(FIFO,First In First Out)的原则。

二、queue的常用接口

函数说明接口说明
queue()构造空的队列
empty()检测queue是否为空
size()返回queue中的元素个数
front()返回队头元素的引用
back()返回队尾元素的引用
push()在队尾将元素val入队列
pop()将队头元素出队列

三、queue的模拟实现

我们来借助deque来模拟实现一下:

namespace Queue { template<class T,class Con=deque<T>> // template<class T,class Con=lsit<T>> class queue { public: queue() { // ... } void push(const T& x) { _c.push_back(x); } void pop() { _c.pop_front(); } T& back() { return _c.back(); } const T& back() const { return _c.back(); } T& front() { return _c.front(); } const T& front() const { return _c.front(); } size_t size() const { return _c.size(); } bool empty() const { return _c.empty(); } private: Con _c; }; } 

同样我们来个简单测试示例:

int main() { Queue::queue<int> q; q.push(10); q.push(20); q.push(30); q.push(40); q.push(50); cout << "队列大小:" << q.size() << endl; cout << "队列首元素:" << q.front() << endl; cout << "队列尾元素:" << q.back() << endl; q.pop(); cout << "队列大小:" << q.size() << endl; cout << "队列首元素:" << q.front() << endl; cout << "队列尾元素:" << q.back() << endl; cout << "Is queue empty? " << (q.empty() ? "Yes" : "No") << endl; while (!q.empty()) { q.pop(); } cout << "Is queue empty? " << (q.empty() ? "Yes" : "No") << endl; return 0; }

输出结果为:

标准库中的priority_queue

一、priority_queue的基本概念

priority_queue(优先级队列)是C++标准库中的一个容器适配器,它提供了一种以堆(heap)为底层结构的优先队列,支持高效的插入和最大(或最小)元素的提取操作。

priority_queue中的元素按照一定的优先级进行排序,每次取出的元素都是优先级最高的。它的底层实现通常使用堆数据结构,堆是一种具有特定性质的二叉树,可以高效地插入新元素和取出优先级最高的元素。 在priority_queue中,默认情况下采用最大堆实现,即优先级最高的元素(最大值)存储在根节点。但也可以通过自定义比较函数,将其转化为最小堆等其他形式。

二、priority_queue的常用接口

函数说明接口说明
priority_queue()/priority_queue(first,last)构造空的优先级队列
empty()检测优先级队列是否为空
size()返回queue中的元素个数
top()返回优先级队列中的最大(最小)元素,堆顶元素
push(x)在优先级队列中插入元素x
pop()删除优先级队列中的最大(最小)元素,即堆顶元素

三、priority_queue的使用

1.默认情况下,priority_queue是大堆。        

#include<iostream> #include<vector> #include<queue> #include<functional> // greater模板类所需要包含的头文件 using namespace std; int main() { // 默认创建的是大堆 vector<int> v{ 3,1,5,2,9,8,7,0,6,4 }; priority_queue<int> Q; for (auto& ele : v) { Q.push(ele); } cout << Q.top() << endl; // 创建小堆 priority_queue<int, vector<int>, greater<int>>q(v.begin(), v.end()); cout << q.top() << endl; return 0; }

std::greater是一个模板类,它实现了一个仿函数(function object),用于比较两个对象的大小。通过重载()操作符,greater可以接受两个参数,并返回第一个参数是否大于第二个参数的布尔值。如果第一个参数大于第二个参数,则返回true;否则返回false。

输出结果为:

2.如果需要在priority_queue中存放自定义类型的数据,则需要在自定义类型中提供>或者<的重载。

class Date { public: Date(int year = 2000, int month = 1, int day = 1) : _year(year) , _month(month) , _day(day) { // ... } bool operator<(const Date& d) const { return (_year < d._year) || (_year == d._year && _month < d._month) || (_year == d._year && _month == d._month && _day < d._day); } bool operator>(const Date& d) const { return (_year > d._year) || (_year == d._year && _month > d._month) || (_year == d._year && _month == d._month && _day > d._day); } friend ostream& operator<<(ostream& _cout, const Date& d) { _cout << d._year << "-" << d._month << "-" << d._day; return _cout; } private: int _year; int _month; int _day; }; int main() { // 大堆,需要用户在自定义类型中提供<的重载 priority_queue<Date> q1; q1.push(Date(2018, 10, 29)); q1.push(Date(2018, 10, 28)); q1.push(Date(2018, 10, 30)); cout << q1.top() << endl; // 如果要创建小堆,需要用户提供>的重载 priority_queue<Date, vector<Date>, greater<Date>> q2; q2.push(Date(2018, 10, 29)); q2.push(Date(2018, 10, 28)); q2.push(Date(2018, 10, 30)); cout << q2.top() << endl; return 0; }

输出结果为:

结束语

我们简单的学习了一下stack和queue的内容,希望能对友友们有所帮助!!!

求点赞收藏评论关注!!!

感谢各位大佬!!!

Read more

Spring 核心技术解析【纯干货版】- XV:Spring 网络模块 Spring-Web 模块精讲

Spring 核心技术解析【纯干货版】- XV:Spring 网络模块 Spring-Web 模块精讲

Spring Framework 作为 Java 生态中最流行的企业级开发框架,提供了丰富的模块化支持。其中,Spring Web 模块是支撑 Web 开发的基础组件,无论是传统的 MVC 应用,还是 REST API 及微服务架构,都离不开它的核心能力。 本篇文章将深入解析 Spring Web 模块的核心概念、依赖关系、作用及关键组件,并通过实际案例展示如何使用 Spring Web 进行 RESTful API 调用。本文力求内容精炼、干货满满,帮助你掌握 Spring Web 的核心技术点。 文章目录 * 1、Spring-Web 模块介绍 * 1.1、Spring-Web 模块概述 * 1.2、Spring-Web

By Ne0inhk
《Web 自动化测试入门:从概念到百度搜索实战全拆解》

《Web 自动化测试入门:从概念到百度搜索实战全拆解》

一、自动化的核心概念 1. 定义:通过自动方式替代人工操作完成任务,生活中常见案例(自动洒水机、自动洗手液、超市闸机)体现了 “减少人力消耗、提升效率 / 质量” 的特点。 2. 软件自动化测试的核心目的: * 用于回归测试:软件迭代新版本时,验证新增功能是否影响历史功能的正常运行。 3. 常见面试题解析: * 自动化测试不能完全取代人工测试:需人工编写脚本,且功能变更后需维护更新,可靠性未必优于人工。 * 自动化测试不能 “大幅度降低工作量”:仅能 “一定程度” 减少重复工作,需注意表述的严谨性。 二、自动化测试的分类 自动化是统称,包含多种类型,核心分类及说明如下: 分类说明接口自动化针对软件接口的测试,目的是验证接口的功能、性能、稳定性等。UI 自动化 针对软件界面的测试,包含: 1. 移动端自动化:通过模拟器在电脑上编写脚本,测试手机应用;稳定性较差(受设备、

By Ne0inhk

如何高效调用Qwen3-VL?这个WEBUI镜像让你事半功倍

如何高效调用Qwen3-VL?这个WEBUI镜像让你事半功倍 在多模态AI迅速演进的今天,开发者面临的最大挑战已不再是“有没有模型可用”,而是“能否快速、低成本地将模型集成到实际业务中”。尽管许多视觉-语言大模型(VLM)在技术指标上表现惊艳,但复杂的部署流程、高昂的硬件门槛和漫长的环境配置,往往让大多数团队望而却步。 而 Qwen3-VL-WEBUI 镜像的出现,彻底改变了这一局面。作为阿里开源的一站式多模态推理解决方案,它内置了强大的 Qwen3-VL-4B-Instruct 模型,封装了完整的运行时环境与交互界面,真正实现了“一键启动、开箱即用”的极致体验。无需拉代码、不需手动安装依赖、不必配置GPU驱动——你只需要一个支持Docker的环境,就能在几分钟内拥有自己的多模态AI助手。 这不仅是一次技术升级,更是一种使用范式的跃迁:从“工程部署”走向“服务调用”。 为什么你需要 Qwen3-VL-WEBUI? 传统方式调用多模态模型通常涉及以下步骤: 1. 下载模型权重(数十GB) 2. 安装PyTorch、Transformers等深度学习框架 3. 编写推理

By Ne0inhk
WebGIS开发实战:WKT转GeoJSON的多种技巧与Leaflet加载应用详解

WebGIS开发实战:WKT转GeoJSON的多种技巧与Leaflet加载应用详解

目录 前言 一、WKT后台转换实现 1、基于PostGIS实现 2、GeoTools实现 二、wellknown.js转换 1、wellknown.js是什么? 2、wellknown.js的方法 三、在Leaflet.js中集成wellknow.js 1、资源引入 2、将wkt转为geojson 四、总结 前言         在当今数字化浪潮中,地理信息系统(GIS)技术正以前所未有的速度融入我们的生活与工作。从城市规划到环境监测,从物流配送到旅游出行,地理空间数据的价值日益凸显。而 WebGIS,作为 GIS 技术与 Web 技术的深度融合,更是为地理信息的共享与交互开辟了广阔天地。它让地理数据能够通过网络在各种终端设备上轻松呈现,极大地拓展了 GIS 的应用场景和受众群体。然而,在 WebGIS

By Ne0inhk