[STL --stack_queue详解]stack、queue,deque,priority_queue

2024-09-02 22:20

本文主要是介绍[STL --stack_queue详解]stack、queue,deque,priority_queue,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

stack

stack介绍

1、stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。
2、stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

 stack的使用

常用操作:

push尾部插入
pop尾部删除元素
top取栈顶元素
empty判空操作

stack的模拟实现

从stack的接口中,我们发现stack是一种特殊的vector,因此可以用vector完全模拟实现stack;

namespace bit {/*template<class T>class stack {private:T* _a;int _top;int _capacity;};*///可维护性//设计模式//适配器  -- 转换template<class T,class Container =vector<T>>class stack {public:void push(const T&x) {_con.push_back(x);}void pop() {_con.pop_back();}bool empty() {return _con.empty();}const T& top() {return _con.back();}size_t size() {return _con.size();}private:Container _con;};
}

当然用list,deque也可以模拟实现栈;

bit::stack<int, list<int>>s;
bit::stack<int, vector<int>>s;
bit::stack<int, deque<int>>s;

queue

queue介绍

1. 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。
2. 队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。

queue的使用

push队尾插入
pop对头删除
front返回对头元素的引用
back返回队尾元素的引用
empty队列是否为空
size队列元素有效个数

priority_queue 

这里的priority_queue是按照优先级出的,底层实现是堆结构;

这里补充一下要用到的堆的知识点:

堆向上调整:

		void AdjustUp(int child) {int parent = (child - 1)/2;while (child>0) {if (_con[parent]< _con[child]) {swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else {break;}}}

堆向下调整:

void AdjustDown(int parent) {int child = parent * 2 + 1;while (child < _con.size()) {if (child+1<_con.size() && _con[child] < _con[child + 1]) {child++;}if (_con[parent] < _con[child]) {swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else {break;}}}

在模拟实现优先队列前,我们先了解一下仿函数:

 仿函数是什么?

看一段代码:

class Func {
public:
    //operator()就是函数名
    void operator()() {
        cout << "func调用" << endl;
    };
};

调用:

    Func f;
    f();
    f.operator()();

 仿函数(Functor) 是一种行为类似函数的对象,它可以被用作函数并接受参数。在C++中,仿函数通常是重载了函数调用运算符operator()的类对象。通过重载operator(),仿函数可以像函数一样被调用,并且可以保存状态信息。

这样利用仿函数,我们就可以把向上调整和向下调整修改调用仿函数:

这样我们需要大堆或者小堆的话就不要每次都修改<,>了,

    template<class T,class Container = vector<T>,class Compare=myless<T>>

 只需要:

默认是大堆;

小堆: 

   bit::priority_queue<int, vector<int>, bit::mygreater<int>>q1(v.begin(), v.end());

下面让我们来模拟实现优先队列:

namespace bit {//仿函数template<class T>class myless {public:bool operator()(const T& x, const T& y) {return x < y;}};//仿函数template<class T>class mygreater {public:bool operator()(const T& x, const T& y) {return x > y;}};template<class T,class Container = vector<T>,class Compare=myless<T>>class priority_queue {public:template <class InputIterator>priority_queue(InputIterator first, InputIterator last) {while (first != last) {_con.push_back(*first);first++;}//建堆(从倒数第一个非叶子节点开始向下调整)for (int i = (_con.size() - 1 - 1) / 2; i >= 0; i--) {AdjustDown(i);}}void AdjustUp(int child) {Compare comfunc;int parent = (child - 1)/2;while (child>0) {if (comfunc(_con[parent], _con[child])) {swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else {break;}}}void AdjustDown(int parent) {Compare comfunc;int child = parent * 2 + 1;while (child < _con.size()) {if (child+1<_con.size() && comfunc(_con[child] , _con[child + 1])) {child++;}if (comfunc(_con[parent] , _con[child])) {swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}else {break;}}}void push(const T& x) {_con.push_back(x);AdjustUp(_con.size()-1);}void pop() {swap(_con[0], _con[_con.size() - 1]);_con.pop_back();AdjustDown(0);}const T& top() {return _con[0];}bool empty() {return _con.empty();}size_t size() {return _con.size();}private:Container _con;//底层核心};
}

queue的模拟实现

由于queue是一个双端操作,这里最后不要使用vector在模拟实现,如果用的话反而会比较麻烦。

可以选择list和deque来模拟实现;

    bit::queue<int, list<int>>s;
    bit::stack<int, deque<int>>s;

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();}bool empty() {return _con.empty();}size_t size() {return _con.size();}const T&top() {return _con.front();}private:Container _con;};
}

deque简单介绍

deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1),与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。

简单的说,deque在功能上就是vector和list的结合。

deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的,实际deque类似于一个动态的二维数组。
 

这篇关于[STL --stack_queue详解]stack、queue,deque,priority_queue的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131226

相关文章

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

mac中资源库在哪? macOS资源库文件夹详解

《mac中资源库在哪?macOS资源库文件夹详解》经常使用Mac电脑的用户会发现,找不到Mac电脑的资源库,我们怎么打开资源库并使用呢?下面我们就来看看macOS资源库文件夹详解... 在 MACOS 系统中,「资源库」文件夹是用来存放操作系统和 App 设置的核心位置。虽然平时我们很少直接跟它打交道,但了

关于Maven中pom.xml文件配置详解

《关于Maven中pom.xml文件配置详解》pom.xml是Maven项目的核心配置文件,它描述了项目的结构、依赖关系、构建配置等信息,通过合理配置pom.xml,可以提高项目的可维护性和构建效率... 目录1. POM文件的基本结构1.1 项目基本信息2. 项目属性2.1 引用属性3. 项目依赖4. 构

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

PyTorch使用教程之Tensor包详解

《PyTorch使用教程之Tensor包详解》这篇文章介绍了PyTorch中的张量(Tensor)数据结构,包括张量的数据类型、初始化、常用操作、属性等,张量是PyTorch框架中的核心数据结构,支持... 目录1、张量Tensor2、数据类型3、初始化(构造张量)4、常用操作5、常用属性5.1 存储(st

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

Python在固定文件夹批量创建固定后缀的文件(方法详解)

《Python在固定文件夹批量创建固定后缀的文件(方法详解)》文章讲述了如何使用Python批量创建后缀为.md的文件夹,生成100个,代码中需要修改的路径、前缀和后缀名,并提供了注意事项和代码示例,... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5.