C++学习指南(七)——stack/queue/priority_queue

embedded/2025/1/11 15:43:52/

        欢迎来到繁星的CSDN,本期内容主要包括stack(栈),queue(队列),priority_queue(堆)

        

    实际上,C++中的stack、queue还有priority_queue与C语言中的内容无异,所以本篇文章主要想去阐述的,是有关stack、queue还有priority_queue的一些接口与实现原理。 

一、deque

    在说明栈、队列以及优先队列是如何实现之前,我们必须阐述deque的相关知识。

    deque是什么?为什么要有deque?以及deque在模拟实现中扮演着什么样的角色?

 

   当我们翻到stl库里的stack和queue的头文件时(只需要在VS2022所在盘搜索stl_queue.h和stl_stack.h即能得到其头文件,这边推荐使用everything软件辅助快速寻找)我们可以看到Sequence的缺省值是deque<_Tp>,Sequence在后续的代码中不难发现是起容器的作用,而_Tp则扮演了stack内存储值的类型。

      deque是什么以及为什么用deque

        

   deque实际上是vector与list的结合体,由多个vector组成,并以list的形式串连起来。

   这么做的好处是什么?

   让我们回想stack和queue的特点,一个是先进先出,一个是后进先出。如果都用vector来储存的话,那么stack需要的是pop_back(),queue需要的是pop_front()。但是用vector来pop_back简单,pop_front就难上加难了,用list的话首尾删除插入倒是方便,但是在存储空间上由于存储的地址不连续性,以及list每个结点所需要存储的信息更多,使得整体耗费的存储空间更大,且首插尾插效率很低。

   于是deque,一个结合了vector与list的东西诞生了。

   很可惜的是,事实上deque结合了vector和list的优点,更结合了vector与list的缺点。进行尾删操作尚且简单,如果进行头删则需要将其他位置所有的数据向前搬一格。如果进行插入操作,则每次插入都有可能多一个同样长度的vector,一插一删之间,deque很可能造成大量的空间浪费,亦或是牺牲了“搬迁”的效率。

    或许在平均效率上deque比单纯用vector或者list更高吧,但stl创建者选用deque的原因我们不得而知。

二、stack和queue的接口

        stack和queue的接口是十分类似的。

push(x);
pop();
empty();
size();
top();//stack
front();//queue
back();//queue

        与string的区别是,string是push_back,但stack和queue是push。string是pop_back,但stack和queue是pop。queue的front和back分别代表第一个元素以及最新被push的元素。stack的top表示栈顶,没有栈底接口。

     为什么要坚持用接口?

       这一点实际上在封装的那一部分已经被提到过了。我们用接口的目的一方面是为了更简单地使用这些复杂的数据结构,一方面是为了数据的安全性,我们只能使用接口对这些结构进行改造,而不能直接从底层的vector或者deque改数据,这种操作对于结构而言是“不合法”的(对于程序而言并没有什么问题)。

三、priority_queue

       优先队列(priority_queue)实际上是堆,其优先性区分了大根堆与小根堆,但值得注意的是,如果需要使用priority_queue,我们需要包的头文件是<queue>。

       template<class T,class Container = std::vector<T>,class Compare = std::less<typename Container::value_type>> class priority_queue; 

        默认的优先队列是大根堆,在日常使用中我们仅仅需要输入堆所存储的数据类型即可。如果需要小根堆,那么就需要输入数据类型,存储容器(一般为vector),以及std::greater<>(递增)。或者自己书写仿函数。

        优先队列的常用接口如下:

push(x);
pop();
top();
empty();
size();

        其中push放入后,优先队列会自动进行排序,top即堆的根,pop即弹出堆的根,size和empty就不过多赘述了。

        下面是大致的模拟实现。

        

#pragma once
#include<deque>
template<class T,class Con = std::deque<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.back();}bool empty()const {return _c.empty();}
private:Con _c;
};
#pragma once
#include<deque>
template<class T, class Con = std::deque<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;
};
#pragma once
namespace bit
{
#include<vector>
#include<functional>template <class T, class Container = std::vector<T>, class Compare = std::less<T> >class priority_queue{public:priority_queue();template <class InputIterator>priority_queue(InputIterator first, InputIterator last) {std::make_heap(first,last,comp);}bool empty() const {return c.empty();}size_t size() const {return c.size();}T& top() const {return c.front();}void push(const T& x) {x.push_back(x);std::push_heap(c.begin(), c.end(), comp);}void pop() {std::pop_heap(c.begin(), c.end(), comp);c.pop_back();}private:Container c;Compare comp;};
};


http://www.ppmy.cn/embedded/153049.html

相关文章

Docker系列---【离线安装docker-compose】

1.安装docker-compose 查看系统版本,如下可知&#xff0c;系统是X86_64的 uname -r 2.下载文件 打开github.com官网&#xff0c;在登录页面的右上角搜索compose找到docker/compose再找releases&#xff0c;(网址&#xff1a;https://github.com/docker/compose/releases) 如下找…

【Docker】docker compose 安装 Redis Stack

注&#xff1a;整理不易&#xff0c;请不要吝啬你的赞和收藏。 前文 Redis Stack 什么是&#xff1f; 简单来说&#xff0c;Redis Stack 是增强版的 Redis &#xff0c;它在传统的 Redis 数据库基础上增加了一些高级功能和模块&#xff0c;以支持更多的使用场景和需求。Redis…

如何进行单体前后端项目的微服务改造

如何进行单体前后端项目的微服务改造 引言 随着互联网技术的快速发展&#xff0c;传统的单体架构&#xff08;Monolithic Architecture&#xff09;逐渐显现出其局限性。对于大型应用来说&#xff0c;单体架构可能会导致开发效率低下、部署困难以及扩展性差等问题。因此&…

聊天机器人Rasa面试内容整理-如何进行实体抽取(Entity Extraction)?

在 Rasa 中,实体抽取(Entity Extraction) 是指从用户输入中识别出关键的信息(例如地点、时间、数字、产品名等)。Rasa 提供了多种方法来执行实体抽取,包括基于规则的方法、机器学习模型以及深度学习模型。不同的实体提取方法可以根据任务的需求进行选择和组合。 实体抽取…

Qt重写webrtc的demo peerconnection

整个demo为&#xff1a; 可以选择多个编码方式&#xff1a; cmake_minimum_required(VERSION 3.5)project(untitled LANGUAGES CXX) set(CMAKE_CXX_STANDARD 20) set(CMAKE_INCLUDE_CURRENT_DIR ON)set(CMAKE_AUTOUIC ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTORCC ON)set(CMA…

人工智能之基于阿里云快速搭建Llama-3.2-11B-Vision-Instruct

人工智能之基于阿里云快速搭建Llama-3.2-11B-Vision-Instruct 需求描述 基于阿里云搭建图片生成文字模型&#xff0c;模型名称&#xff1a;LLM-Research/Llama-3.2-11B-Vision-Instruct使用上述模型输入图片生成文字&#xff0c;模型路径 业务实现 阿里云配置 阿里云配置如…

for循环暴力解法以及优化练习

这里主要是练习一下用等差数列解决for循环的时间复杂度的一些问题 公式&#xff1a; 等差数列求和公式&#xff1a;&#xff08;首尾&#xff09;*项数/2 等差数列项数公式&#xff1a;&#xff08;尾-首&#xff09;/公差1 有一组数组比如&#xff1a;1&#xff0c…

通信网络安全分层及关键技术解决

要实现信息化&#xff0c;就必须重视信息网络安全。信息网络安全绝不仅是IT行业的问题&#xff0c;而是一个社会问题&#xff0c;是一个包括多学科的系统安全工程问题&#xff0c;并直接关系到国家安全。因此&#xff0c;知名安全专家沈昌祥院士呼吁&#xff0c;要像重视两弹一…