stack、queue、priority_queue以及仿函数

我们上次对std中的list进行实现,今天我们要实现stack、queue、priority_queue以及仿函数。

目录

  • stack堆
    • 堆的框架
    • 构造函数
    • push插入
    • pop删除
    • size()大小
    • empty()判断空
    • top()取栈顶的元素
  • queue队列
    • 队列框架
      • 问题: 这里我们为什么用deque?
    • 插入
    • 删除
    • 取头数据
    • 取尾数据
    • 判断空和大小
  • priority_queue堆
    • priority_queue的架构
      • empty()判断空
      • size()大小
      • top()取堆顶元素
      • sawp()交换
      • push()插入
      • pop()删除
    • 仿函数
      • 仿函数架构

stack堆

堆的原则就是先进后出,后进先出。如图:
在这里插入图片描述

从上图我们可以看出来stack准确说就是一个vector,所以我们就可以利用vector来建。

堆的框架

既然是实现STL库,一定是相似与库中,我们先不看他用的是谁,我们刚刚也分析了用vector来实现,所以我们可以用vector来封装。
在这里插入图片描述
这里的Con表示Container(容器),我们只需要传一个容器类型就可以,这里用vector是因为stack的特性,也可以用deque(他是链表与顺序表的结合,这里不会多说)。

    template<class T, class Con = vector<T>>class stack{public:private:Con _c;};

构造函数

没错,你没看错,这里我们的构造函数什么都没有写,其实你不写构造函数也可以,我们也说了构造函数对内置类型不做处理,但是对内置类型会去调用它的默认构造,这里我们用了container容器,我们传什么容器类型就是什么容器,我们就可以间接区调用它的构造函数

stack()
{}

push插入

push其实很简单,vector中插入数据是不是用的push_back();那么我们可以调用那个成员函数,来达到插入效果。
在这里插入图片描述

 void push(const T& x){_c.push_back(x);}

pop删除

pop也是一样的。复用接口。因为我们是后进的先出,所以我们就尾删。

       void pop(){_c.pop_back();}

size()大小

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

empty()判断空

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

top()取栈顶的元素

那么什么是栈顶呢?如果数据1的位置是0,那么数据3的位置一定是n-1,所以我们有了size就可以,用size()-1;而且vector支持下标。
在这里插入图片描述

  T& top(){return _c[size() - 1];}

queue队列

队列的特性是先进先出,后进后出
在这里插入图片描述

队列框架

其实队列和栈的框架是一样的。

template<class T, class Con = deque<T>>class queue{public:private:Con _c;};

问题: 这里我们为什么用deque?

因为头删问题,我们也知道头删vector是效率很低的,你会说为什么不用list,list不支持下标访问,但是这里用deque就能很好的避免,因为库中deque既有头删,也可以下标访问
在这里插入图片描述

deque的结构其实就是链表和vector的结合。但是deque的缺点也很致命。

  • deque的优点
    ①.头插尾插很快,不需要挪数据,只需要开空间插入
    ②支持连续访问
  • deque的缺点
    ①.中间的插入删除效率麻烦且一般。
    ②.方括号的效率并不极致。

插入

void push(const T& x)
{_c.push_back(x);
}

删除

void pop()
{_c.pop_front();
}

取头数据

 T& front(){return _c.front();}const T& front()const{return _c.front();}

取尾数据

        T& back(){return _c.back();}const T& back()const{return _c.back();}

判断空和大小

  size_t size()const{return   _c.size();}bool empty()const{return  _c.empty();}

priority_queue堆

优先级队列和队列没有任何关系!优先级队列是堆,并且他默认是大堆!我们看库中会发现,他和queue共用一个头文件。
在这里插入图片描述

我们在看一下库中的实现。有模板参数有 T、Container、那么Compare是啥啊?我们先不管,看库的时候,遇到不懂得,我们可以先往下看看,如果不影响我们就先不看他,所以我们先排除Compare。先把架子搭出来。
在这里插入图片描述

priority_queue的架构

我们还是复用容器类型,堆是完全二叉树,并且之前我们用vector就可以,通过上下调整位置,达到堆。

template<class T ,class Container=vector<T>, class Compare = less<T> >
class priority_queue
{
public:private:Container _con;
};

在这里插入图片描述

empty()判断空

我们从上图可以看出来priority_queue的成员函数并不多。

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

size()大小

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

top()取堆顶元素

堆顶元素是谁?是不是root根啊,我们用的也是vector,所以堆顶很好取。

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

sawp()交换

	void swap(T& p1,T&p2){std::swap(p1,p2);}

push()插入

我们之前学习堆的时候插入是怎么插入的?插到尾部,然后不断向上调整。如图,默认是大堆,我们在尾巴插入一个20,向上调整。通过父子对比,孩子比父亲大,我们就向上调整。
在这里插入图片描述

		void push(const T& x){//尾插然后向上调整_con.push_back(x);AdjustUp(size()-1);}void AdjustUp(int child){//Compare c;int parent = (child - 1) / 2;//找父亲while (child > 0){//不断调整,直到不满足要求了,结束//if (_con[child] > _con[parent])//if (c(_con[parent], _con[child]))if (_con[parent]<_con[child]){swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}}

pop()删除

库中说从顶部移除元素,所以我们需要删除堆顶。删除堆顶元素,我们可以首尾交换,然后尾删,向下调整
在这里插入图片描述
如图:
在这里插入图片描述

void pop()
{//头尾交换,删除,然后向下调整swap(_con[0], _con[size() - 1]);_con.pop_back();AdjustDown(0);
}
void AdjustDown(int parent)
{//Compare c;int child = parent * 2 + 1;while (child < size()){if (child < size() - 1 && _con[child] < _con[child + 1])//if (child < size() - 1 && c(_con[child], _con[child + 1])){//这里需要判断一下,因为我们找的都是左子树,判断一下右子树是否存在//如果存在,在判断一下那个大,哪个大就和哪个换。(默认大堆)child++;}if (_con[parent] < _con[child])//if (c(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}elsebreak;}
}

仿函数

上述我们只能实现默认的大堆,现在如果我希望你实现一个小堆,你怎么办?ok,你会说我修改一下大于小于号,那么如果在实战的项目中,让你实现,你会和客户说等我一下,我修改一下大于小于号?那不可能,那怎么做呢?仿函数!

其实我们也见过仿函数,在排序中,我们可以利用仿函数排升序降序。
在这里插入图片描述
如果你在C语言阶段用过排序qsort();里面是不是会让你们传一个函数指针类型?其实仿函数就是解决了回调函数问题(函数指针)。

仿函数架构

其实在我们上面写priority_queue的时候,你会发现默认给的less却是大堆,这个我也不知道为什么,记住就好了。其实仿函数,你可以理解为,只要重载了operator() 就算是仿函数
你看输出的时候,是不是特别像一个函数?其实并不是的,其实只是重载了小括号。
在这里插入图片描述

	template<class T>class less{//控制大堆public:bool operator()( const T& x,const T&y){return x < y;}};template<class T>class greater{//控制小堆public:bool operator()(const T& x, const T& y){return x > y;}};template<class T ,class Container=vector<T>, class Compare = less<T> >class priority_queue{public:void push(const T& x){//尾插然后向上调整_con.push_back(x);AdjustUp(size()-1);}void pop(){//头尾交换,删除,然后向下调整swap(_con[0], _con[size() - 1]);_con.pop_back();AdjustDown(0);}private:void AdjustDown(int parent){Compare c;int child = parent * 2 + 1;while (child < size()){//if (child < size() - 1 && _con[child] < _con[child + 1])if (child < size() - 1 && c(_con[child], _con[child + 1])){child++;}//if (_con[parent] < _con[child])if (c(_con[parent], _con[child])){swap(_con[child], _con[parent]);parent = child;child = parent * 2 + 1;}elsebreak;}}void AdjustUp(int child){Compare c;//创建比较的对象int parent = (child - 1) / 2;while (child > 0){//if (_con[child] > _con[parent])//if (_con[parent]<_con[child])if (c(_con[parent], _con[child]))//传哪个仿函数调哪个{swap(_con[child], _con[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}}Container _con;};

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

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

相关文章

AI交互数字人赋能农业数字化、智能化推广营销

2024陵水荔枝文化节上“数字新农人”陵小荔身着黎族服饰、佩戴银器亮相开幕式现场&#xff0c;AI交互数字人生动地以互动式推介和歌舞等形式&#xff0c;带领宾客们了解陵水荔枝的发展历程、产业布局、未来愿景等。如今&#xff0c;越来越多农产品品牌通过3D虚拟数字人定制&…

最详细的提单知识总结 | 数字贸易综合服务平台 | 箱讯科技

在外贸交易中&#xff0c;国际物流是必不可少的一个步骤。国际物流掌控好&#xff0c;就等于把货物牢牢握在手心&#xff0c;不怕货财两空。 本期将向大家介绍正本提单、电放提单、海运单三种国际海运放货方式以及区分它们的方法。 超实用&#xff01;外贸人赶紧收藏~ 正本提…

CTF例题:[SWPU2019]Web1(无列名注入)

网址&#xff1a;BUUCTF在线评测 搜索web1 启动靶机 点击链接进入题目 进入题目后发现有登录和注册接口&#xff0c;直接注册登录。 首先通过1进行测试&#xff0c;查看是否有注入点 出现报错&#xff0c;说明可能存在注入点 然后继续测试发现该服务器过滤了&#xff1a; or、…

vue(九) 生命周期 v3.0和v2.0对比,父子组件生命周期的执行顺序

文章目录 生命周期vue2.0生命周期1.图示2.生命周期解释说明3.代码示例 vue3.0生命周期1.图示2.生命周期解释说明3.代码示例 父子组件中生命周期执行顺序v.3和v2.0生命周期对比 生命周期 每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤&#xff0c;比如设置好数据侦听…

怎么做私域?先来了解私域运营模式!

现在&#xff0c;很多企业都在做私域&#xff0c;但仍旧有很多人会问&#xff1a;我的私域到底要怎么做&#xff1f; 关于这个问题&#xff0c;不同产品无论在消费频次与客单价上&#xff0c;还是在决策链路的长度和复杂度上&#xff0c;都有巨大的差异&#xff0c;消费者需要…

如何使用AspectJ做切面,打印jar包中方法的执行日记

最近在工作中遇到一个redis缓存中的hash key莫名其妙被删除的问题&#xff0c;我们用了J2Cache&#xff0c;二级缓存用的是redis。hash key莫名其妙被删除又没有日志&#xff0c;就想到做一个切面在调用redis删除hash key的方法的时候&#xff0c;打印日志&#xff0c;并且把调…

高德、百度开车导航APP是怎么知道红绿灯倒计时的?

高德、百度开车导航APP之所以能够知道红绿灯的倒计时&#xff0c;这背后是一系列复杂的科技手段和数据分析的综合运用。从交管部门提供的数据&#xff0c;到导航软件自身通过大数据和算法进行的计算&#xff0c;每一个环节都为红绿灯倒计时的准确呈现提供了支撑。 首先&#xf…

白酒:低酒精度白酒的消费特点与市场前景

低酒精度白酒的消费特点与市场前景是酒类市场的一个重要话题。随着品质意识的提高和消费者口味的多样化&#xff0c;低酒精度白酒逐渐受到越来越多的关注。云仓酒庄豪迈白酒作为白酒的品牌之一&#xff0c;其消费特点和市场前景值得深入探讨。 首先&#xff0c;从消费特点来看…

基于YOLOv5的道路裂缝检测,加入一种基于内容引导注意力(CGA)的混合融合提升2个多点

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文主要内容:详细介绍道路裂缝检测整个过程&#xff0c;从数据集到训练模型到结果可视化分析。 &#x1f4a1;&#x1f4a1;&#x1f4a1;通过加入一种基于内容引导注意力(CGA)的混合融合提升检测性能&#xff0c; 特征融合创新 | 一…

WS2812C是一款将控制电路和RGB芯片集成在一个5050元器件封装中的智能控制LED光源

一般说明 WS2812C是一款将控制电路和RGB芯片集成在一个5050元器件封装中的智能控制LED光源。内部包括智能数字端口数据锁存器和信号整形放大驱动电路。还包括一个精密的内部振荡器和一个 12V电压可编程恒流控制部分&#xff0c;有效保证像素点光源颜色高度一致。 …

决策规划仿真平台的搭建

以下内容笔记据来自于b站up主忠厚老实的老王&#xff0c;视频&#xff1b;链接如下&#xff1a; 自动驾驶决策规划算法第二章第一节 决策规划仿真平台搭建_哔哩哔哩_bilibili 使用到的软件有matlab、prescan、carsim以及visual stadio。 我电脑上软件的版本是matlab2022a&am…

2024.1IDEA 到2026年

链接&#xff1a;https://pan.baidu.com/s/1hjJEV5A5k1Z9JbPyBXywSw?pwd9g4i 提取码&#xff1a;9g4i解压之后,按照 操作说明.txt 操作; IntelliJ IDEA 2024.1 (Ultimate Edition) Build #IU-241.14494.240, built on March 28, 2024 Licensed to gurgles tumbles You have…

Python代码:二、多行输出

1、题目 将字符串 Hello World! 存储到变量str1中&#xff0c;再将字符串 Hello Nowcoder! 存储到变量str2中&#xff0c;再使用print语句将其打印出来&#xff08;一行一个变量&#xff09;。 2、代码 import sys str1 Hello World! str2 Hello Nowcoder! print (str1,st…

详细分清Session,Cookie和Token之间的区别,以及JWT是什么东西

Cookie Cookie是一种小型的文本文件&#xff0c;由网站在用户访问时存储在其计算机或移动设备上&#xff0c;Cookie主要用于跟踪、识别和存储有关用户的信息。 简单来说Cookie就是用来存储某些后端发送给前端的数据&#xff0c;例如我们登陆后&#xff0c;后端会返回一个登录…

C++ requires关键字简介

requires 是 C20 中引入的一个新关键字&#xff0c;用于在函数模板或类模板中声明所需的一组语义要求&#xff0c;它可以用来限制模板参数&#xff0c;类似于 typename 和 class 关键字。 requires关键字常与type_traits头文件下类型检查函数匹配使用&#xff0c;当requires后…

激光雷达技术:科技之眼,照亮前行

在科技与人文关怀的交响乐章中&#xff0c;一项名为“蝙蝠避障”使用了激光雷达技术原理及应用的创新成果&#xff0c;正悄然改变着视障朋友们的生活方式&#xff0c;为他们的日常出行铺设了一条充满希望的光明之路。今天&#xff0c;让我们一起深入探讨这项技术如何成为盲人出…

深化市场布局与产业链整合,三清互联以创新为公司发展赋能

近年来&#xff0c;我国大力发展现代化电力体系&#xff0c;并不断推进智能电网的发展&#xff0c;电力物联网作为支撑电力行业数字化发展的关键基础设施&#xff0c;迎来了快速发展黄金时期。作为电力物联网领域领先企业之一&#xff0c;三清互联凭借敏锐的市场洞察力和技术创…

探索软件测试中的创新测试方法:测试左移

软件测试中的测试左移方法 在当今竞争激烈的市场中&#xff0c;满足客户的期望和需求是所有公司在竞争中成为市场领导者的关键。这就是为什么越来越多的公司现在转向测试左移&#xff0c;并将其应用于产品开发过程。 在本文中&#xff0c;我们将从初学者的角度来介绍测试左移…

cmd如何以管理员身份运行

打开开始菜单。 在搜索框中输入cmd。 在搜索结果中&#xff0c;找到cmd&#xff0c;右键单击&#xff0c;选择“以管理员身份运行”。 参考&#xff1a; cmd如何以管理员身份运行

刷题之字母异位词(leetcode 哈希表)

https://leetcode.cn/problems/group-anagrams/ class Solution { public:vector<vector<string>> groupAnagrams(vector<string>& strs) {unordered_map<string,vector<string>>map;//哈希表键为排序后或者处理后的字符串&#xff0c;值为某…