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

欢迎来到繁星的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的接口是十分类似的。

cpp 复制代码
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<>(递增)。或者自己书写仿函数。

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

cpp 复制代码
push(x);
pop();
top();
empty();
size();

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

下面是大致的模拟实现。

cpp 复制代码
#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;
};
cpp 复制代码
#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;
};
cpp 复制代码
#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;
    };
};
相关推荐
辞旧 lekkk19 小时前
【Qt】信号和槽
linux·开发语言·数据库·qt·学习·mysql·萌新
2zcode20 小时前
运动模糊图像复原的MATLAB仿真与优化
开发语言·matlab
袁雅倩199720 小时前
当吸尘器、筋膜枪都用上Type-C,供电方案该怎么选?浅谈PD取电芯片ECP5702的应用
c语言·开发语言·支持向量机·动态规划·推荐算法·最小二乘法·图搜索算法
Aaswk21 小时前
Java Lambda 表达式与流处理
java·开发语言·python
万邦科技Lafite21 小时前
京东item_get接口实战案例:实时商品价格监控全流程解析
java·开发语言·数据库·python·开放api·淘宝开放平台
王老师青少年编程1 天前
csp信奥赛C++高频考点专项训练之字符串 --【子串查找】:[NOIP 2009 提高组] 潜伏者
c++·字符串·csp·高频考点·信奥赛·子串查找·潜伏者
Cyber4K1 天前
【Python专项】进阶语法-系统资源监控与数据采集(1)
开发语言·python·php
初願致夕霞1 天前
基于系统调用的Linux网络编程——UDP与TCP
linux·网络·c++·tcp/ip·udp
Le_ee1 天前
ctfweb:php/php短标签/.haccess+图片马/XXE
开发语言·前端·php
yong99901 天前
MATLAB读取高光谱图像
开发语言·matlab