【C++从小白到大牛】栈和队列(优先级队列)

news2024/9/22 19:36:07

目录

引言:

使用方法篇:

stack:

queue

priority_queue

使用方法:

模拟实现篇:

stack:

原码:

queue

原码:

priority_queue

插入和删除数据的思想:

仿函数实现比较

原码:

引言:

本文主要讲解C++ STL库中stack、queue、priority_queue的使用方法和模拟实现。

我们首先需要对stack、queue进行定性,他们跟我们之前讲的string、vector、list一样都是容器吗?

其实并不是。虽然stack和queue中也可以存放元素,列只是对其他容器的接口进行了封装,STL中stack和queue默认使用deque,因为deque这个容器几乎包含了vector和list的所有接口但在STL中并没有将其划分在容器的行列,而是将其称为容器适配器

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

使用方法篇:

stack:

stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。

queue

 队列是一种容器适配器,专门用于在FIFO上下文(先进先出)中操作,其中从容器一端插入元素,另一端提取元素。

priority_queue

1. 优先队列是一种容器适配器,根据严格的弱排序标准,它的第一个元素总是它所包含的元素中最大的。

2. 此上下文类似于堆,在堆中可以随时插入元素,并且只能检索最大堆元素(优先队列中位于顶部的元素)。

使用方法:

优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中元素构造成堆的结构,因此priority_queue就是堆,所有需要用到堆的位置,都可以考虑使用priority_queue。注意:默认情况下priority_queue是大堆

函数说明                               接口说明
empty( )检测优先级队列是否为空,是返回true,否则返回false
top( )返回优先级队列中最大(最小元素),即堆顶元素
push(x)在优先级队列中插入元素x
pop()删除优先级队列中最大(最小)元素,即堆顶元素

模拟实现篇:

stack:

1、stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。

2. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:
empty:判空操作
back:获取尾部元素操作
push_back:尾部插入元素操作
pop_back:尾部删除元素操作

3. 标准容器vector、deque、list均符合这些需求,默认情况下,如果没有为stack指定特定的底层容器,默认情况下使用deque。

因为是容器适配器,所以只是对其他容器的接口进行了封装,因此模拟实现起来非常简单,直接调用原先容器的接口即可,本质上是一种复用!

原码:

namespace kehan
{
    template<class T, class Con = deque<T>>
    class stack
    {
    public:
        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;
    };
}

queue

1、队列作为容器适配器实现,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从队尾入队列,从队头出队列。

2、 底层容器可以是标准容器类模板之一,也可以是其他专门设计的容器类。该底层容器应至少支持以下操作:
empty:检测队列是否为空
size:返回队列中有效元素的个数
front:返回队头元素的引用
back:返回队尾元素的引用
push_back:在队列尾部入队列
pop_front:在队列头部出队列

3. 标准容器类deque和list满足了这些要求。默认情况下,如果没有为queue实例化指定容器类,则使用标准容器deque。

跟stack同理,都是容器适配器,因此直接复用接口即可,与stack使用一些不同的接口,两者区别仅此而已,实现也比较简单。

原码:

namespace kehan
{
    template<class T, class Con = deque<T>>
    class queue
    {
    public:
        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;
    };
};

priority_queue

1、 优先队列被实现为容器适配器,容器适配器即将特定容器类封装作为其底层容器类,queue提供一组特定的成员函数来访问其元素。元素从特定容器的“尾部”弹出,其称为优先队列的顶部。

2、 底层容器可以是任何标准容器类模板,也可以是其他特定设计的容器类。容器应该可以通过随机访问迭代器访问,并支持以下操作:
empty():检测容器是否为空
size():返回容器中有效元素个数
front():返回容器中第一个元素的引用
push_back():在容器尾部插入元素
pop_back():删除容器尾部元素

3、 标准容器类vector和deque满足这些需求。默认情况下,如果没有为特定的priority_queue类实例化指定容器类,则使用vector。

注意优先级队列本质上其实是一个堆!默认是大根堆,可以根据自己的需求更改是大根堆还是小根堆(由仿函数实现)。

因为优先级队列的底层是堆,因此我们在一边push数据,一边建堆。

插入和删除数据的思想:

因此这里的插入数据用到了在数据尾部插入,采用向上调整算法,保证插入过后仍然是堆;

删除数据同理,删除数据指的就是删除堆顶位置的元素,我们先将堆顶位置的元素和堆里面最后一个位置的元素进行交换,然后将最后一个位置的元素pop掉(就是原先的堆顶元素),接着再用向下调整算法进行保证还是一个堆。

仿函数实现比较

仿函数本质上是对操作符()括号的重载,因为有两个括号比较像函数,所以取名为仿函数,但他本质上是一个类!

通过仿函数控制类里面的数据比较逻辑,实现回调

原码:

namespace kehan
{
    //利用仿函数进行比较
    template <class T> 
    class greater
    {
    public:
        bool operator()(T x, T y)
        {
            return x > y;
        }
    };

    template <class T>
    class less
    {
    public:
        bool operator()(T x, T y)
        {
            return x < y;
        }
    };

    template <class T, class Container = vector<T>, class Compare = less<T>>
    class priority_queue
    {
    public:
        //向上调整算法
        void adjustup(int child)
        {
            while (child > 0)
            {
                int parent = (child - 1) / 2;
                if (comp(c[parent], c[child]))//建大堆
                {
                    swap(c[parent], c[child]);
                    child = parent;
                }
                else
                    break;
            }
        }

        //向下调整算法
        void adjustdown(int parent)
        {
            int child = parent * 2 + 1;
            if (child+1 < c.size() && comp(c[child] ,c[child + 1])) child++;
            while (child < c.size())
            {
                if (comp(c[parent], c[child]))
                {
                    swap(c[parent], c[child]);
                    parent = child;
                }
                else
                    break;
                child = parent * 2 + 1;
                if (child+1 < c.size() && comp(c[child], c[child + 1])) child++;
            }
        }

        bool empty() const
        {
            return c.empty();
        }

        size_t size() const
        {
            return c.size();
        }

        const T& top() const
        {
            return c[0];
        }

        void push(const T& x)
        {
            //这里的push就是一个建堆的过程
            c.push_back(x);
            adjustup(c.size()-1);
        }

        void pop()
        {
            swap(c[0], c[c.size() - 1]);
            c.pop_back();
            adjustdown(0);
        }

    private:
        Container c;
        Compare comp;

    };
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

TDEngine(taos) 涛思数据库-sql初识

一、基本使用 这里读者自行安装数据库&#xff1a;使用安装包立即开始 | TDengine 文档 | 涛思数据 (taosdata.com) // 下载gz文件&#xff0c;解压 tar -zxvf TDengine-server-<对应版本>-Linux-x64.tar.gz// 解压后启动 sudo ./install.sh 启动成功后&#xff0c;直…

动态规划之子数组系列问题

题型介绍 子数组系列动态规划问题长什么样 例题 力扣 53. 最大子数组和 解题步骤&#xff1a; 创建 dp 表以及确定 dp 表中所要填写位置的含义&#xff1a; 首先&#xff0c;根据写题经验&#xff0c;先确定出这道题应该使用的解题思路是 “以某一个位置为结尾进行分析”…

【编码心得】单元测试的那些事

【编码心得】单元测试的那些事 文章目录 单元测试定义&#xff1f;为什么需要单元测试&#xff1f;为重构保驾护航提高代码质量减少 bug快速定位 bug持续集成依赖单元测试团队编码规范要求大牛都写单元测试保住面子 TDD 测试驱动开发何谓 TDD&#xff1f;TDD的基本流程TDD 优缺…

全球轻型汽车市场规划预测:2030年市场规模将接近2502亿元,未来六年CAGR为2.8%

一、引言 随着全球经济的发展和消费者出行需求的增加&#xff0c;轻型汽车作为汽车市场中的重要组成部分&#xff0c;其市场重要性日益凸显。本文旨在探索轻型汽车行业的发展趋势、潜在商机及其未来展望。 二、市场趋势 全球轻型汽车市场的增长主要受全球经济发展、消费者对出…

海风小店微信商城小程序附后端一款免费开源的小程序源码

该商城小程序服务端api基于node.jsThinkJSMySQL&#xff0c;如果对这个不大熟悉的人&#xff0c; 可能有那么一点难度&#xff0c;但是如果只是搭建的话&#xff0c;作者的教程还是比较详细的&#xff0c;而且搭建步骤比较简单&#xff0c; 应该很容易上手&#xff0c;如果你…

【KAN】【API教程】索引

简单来说就是确定激活函数的坐标 from kan import *model = KAN(width=[2,3,2,1]) x = torch.normal(0,1,size=(100,2)) model(x); beta = 100 model.plot(beta=beta) # [2,3,2,1] means 2 input nodes # 3 neurons in the first hidden layer, # 2 neurons in the second hid…

知识图谱开启了一个可以理解的人工智能未来

概述 本文是对利用知识图谱&#xff08;KG&#xff09;的综合人工智能&#xff08;CAI&#xff09;的全面调查研究&#xff0c;其中 CAI 被定义为可解释人工智能&#xff08;XAI&#xff09;和可解释机器学习&#xff08;IML&#xff09;的超集。 首先&#xff0c;本文澄清了…

【Linux学习】实现一个简单版的Shell

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;Linux从入门到进阶 欢迎大家点赞收藏评论&#x1f60a; 目录 &#x1f4d5;前言&#x1f351;shell&#x1f4da;Shell的工作原理&#x1f512;Shell的高级功能 &#x1f680;shell的代码实现&am…

Mybatis实战:#{} 和 ${}的使用区别和数据库连接池

一.#{} 和 ${} #{} 和 ${} 在MyBatis框架中都是用于SQL语句中参数替换的标记&#xff0c;但它们在使用方式和处理参数值上存在一些显著的区别。 #{}的作用&#xff1a; #{} 是MyBatis中用于预编译SQL语句的参数占位符。它会将参数值放入一个预编译的PreparedStatement中&am…

JavaScript ES6语法详解(下)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;我是码喽的自我修养&#xff01;今天给大家分享JavaScript ES6语法详解(下)&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到带大家&#xff0c;欢迎收藏关注…

信创企业级即时通讯发展趋势,私有化安全沟通

信创&#xff08;创新型科技公司&#xff09;在当今的商业环境中发挥着重要作用&#xff0c;因此&#xff0c;他们对于私有化安全沟通的需求日益增加。企业级即时通讯软件是为满足企业内部沟通和协作需求而设计的重要工具。在信创企业中&#xff0c;采用私有化安全沟通解决方案…

乐乐音乐Kotlin版

简介 乐乐音乐Kotlin版&#xff0c;主要是基于ExoPlayer框架开发的Android音乐播放器&#xff0c;它支持lrc歌词和动感歌词(ksc歌词、krc歌词、trc歌词、zrce歌词和hrc歌词等)、多种格式歌词转换器及制作动感歌词、翻译歌词和音译歌词。 编译环境 Android Studio Jellyfish | …

计算机毕业设计Python+Tensorflow股票推荐系统 股票预测系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

1、用pycharm打开项目&#xff0c;一定要打开包含manage.py文件所在文件夹 2、配置解释器&#xff1a;建议使用Anaconda(Python 3.8(base))&#xff0c;低于3.8版本的&#xff0c;页面会不兼容 3、安装依赖库&#xff1a;打开pycharm的终端&#xff0c;输入&#xff1a; pip in…

第TR3周:Pytorch复现Transformer

本文为365天深度学习训练营 中的学习记录博客 原作者&#xff1a;K同学啊 任务详情&#xff1a; ●1. 从整体上把握Transformer模型&#xff0c;明白它是个什么东西&#xff0c;可以干嘛 ●2. 读懂Transformer的复现代码&#xff08;暂时不要过于纠结于某一个点&#xff0c;后面…

重生之我们在ES顶端相遇第9 章- 搜索框最常用的功能 - 搜索建议

文章目录 1 前言2 Term Suggester2.1 基本介绍2.2 使用 demo2.3 常用参数2.3.1 suggest_mode2.3.2 max_edits2.3.3 prefix_length2.3.4 min_word_length 3 Completion Suggester3.1 基本描述3.2 基本使用3.3 查询参数3.3.1 size3.3.2 skip_duplicates3.3.3 fuzzy queries(模糊查…

【WPF开发】安装环境、新建工程

一、安装环境 在安装VS时候&#xff0c;勾选安装开发环境 如果已安装VS&#xff0c;可以到工具中查看是否有相应环境 二、新建工程 点击“创建新项目” 通过顶部过滤&#xff0c;C#&#xff0c;选择“WPF应用&#xff08;NET.framework&#xff09;”&#xff0c;并点击“下一…

通过 ACM 论文模版学习 LaTeX 语法 【三、格式】

文章目录 一、LaTeX 简介二、ACM 论文模版三、格式3.1 文章格式3.1.1 注释3.1.2 空格3.1.3 换行 3.2 字体3.2.1 字体样式3.2.2 字体大小2.2.3 字体颜色 一、LaTeX 简介 通过 ACM 论文模版学习 LaTeX 语法 【一、LaTeX简介和安装】 二、ACM 论文模版 通过 ACM 论文模版学习 L…

一款免费开源绿色免安装的透明锁屏工具

一款免费开源绿色免安装的透明锁屏工具 这个工具的特点就是电脑锁屏的时候&#xff0c;仍然显示原桌面&#xff0c;但是无法操作&#xff0c;需要输入密码才可以解锁。输入密码界面也是隐藏的需要按键才能显示输入密码框。 电脑★★★★★透明锁屏工具&#xff1a;https://pa…

canvas-视频绘制

通过Canvas元素来实时绘制一个视频帧&#xff0c;并在视频帧上叠加一个图片的功能可以当作水印。 获取Canvas元素&#xff1a; let canvas document.getElementById(canvas) 通过getElementById函数获取页面中ID为canvas的Canvas元素&#xff0c;并将其存储在变量canvas中。 …