C++相关概念和易错语法(17)(适配器模式、仿函数)

1.stack和queue

stack和queue的相关接口如下:

stack

queue

我们发现不管是stack还是queue,它们都有push和pop,不区分push_back和push_front,这是由它们的入栈特定顺序特性决定的,并且它们都没有迭代器,stack只有top,queue只有front和back这使得我们只能以规定的方式去访问这个stack或者queue

emplace相当于入栈,一般我们用push就可以了。

2.stack和queue的模拟实现

我们已经知道stack、queue和vector、list本质上并没有区别,所以我们可以将复用的思想带到它们的实现中,并且我们可以利用模板对于同一个stack模板,使用不同的底层来实现。这体现了继迭代器模式后的第二种设计模式:适配器模式,即转换。

下面是它们的实现

template<class T, class Container = vector<T>>
class stack
{
public:stack(const Container& con = Container()):_con(con){}void push(const T& val){_con.push_back(val);}		void pop(){_con.pop_back();}		T& top(){return _con.back();}size_t size(){return _con.size();}bool empty(){return _con.empty();}void swap(stack& st){std::swap(_con, st._con);}private:Container _con;
};template<class T, class Container = list<T>>
class queue
{
public:queue(const Container& con = Container()):_con(con){}void push(const T& val){_con.push_back(val);}		void pop(){_con.pop_front();}		T& back(){return _con.back();}		T& front(){return _con.front();}size_t size(){return _con.size();}bool empty(){return _con.empty();}void swap(queue& q){std::swap(_con, q._con);}

我们可以看出,stack和queue的实现几乎不需要自己实现具体功能,我们只需要关注上层功能而不是底层的细节,这极大地体现了封装的特性。

代码中仍有一些细节点需要注意:

(1)为什么只写了构造但没有写析构?为什么构造有缺省值

构造时我们可能空构造,需要缺省值,也有可能带参构造,带参构造需要我们形参接收,这里展示的是拷贝构造的情况,析构的时候成员_con作为自定义类型会去调用自己的析构函数,不会存在内存泄露的情况,所以不需要我们显式的去写析构

(2)swap为什么使用std::swap?

事实上,当我们包含了<vector><list>后,std域里的swap函数就多了几个重载,这几个重载是专门针对vector和list类型的,_con和q._con是Container类型,也就是vector<int>或list<int>类型,会去调用重载的效率较高的swap函数。

之所以std里重载swap函数,就是为了让我们在不知vector类里有swap成员函数的情况下也能高效地交换(只交换指针的值而不是交换所有指向的值)。因此除了这种写法,我们还可以显式调用vector类的成员函数

(3)stack只能以vector作为容器吗?

vector是连续的物理结构,下标访问快,但头插效率极低。因此vector不支持头插头删。在queue中pop使用了pop.front(),在vector里没有这个接口,所以不能使用vector实现queue,但是我们如果用erase来实现pop也可以,这样就可以用vector实现queue了,但并不建议这么做,因为vector实现queue本就是效率极低的做法。

list是分散的物理结构,任意位置插入删除效果都不错,但下标访问效率低。因此list不支持下标访问。但是stack和queue都没用到下标访问,因此我们可以用list实现queue和stack。

事实上,stack和queue在STL中都是以deque作为默认的容器。我们发现,vector和list本就是两个极端的存储结构。所以deque是结合vector、list,能同时进行下标访问和push_back、push_front等操作的容器。

deque用buff小数组+中控数组来实现它的功能,是vector和list存储的结合体,虽然支持下标访问,但它的没vector快,deque[]偶尔用用还行,头尾删除不错。我们适当了解一下deque即可,不用深究,因为deque本不算一个效率高的容器。

3.优先级队列和仿函数

priority_queue本质上是堆,我们只要掌握了堆,优先级队列的核心就能很快完成了。

但是priority_queue用到了仿函数的知识点,在大堆小堆的处理和我们C语言有所不同

(1)仿函数:

仿函数,即模仿函数的一个类,我们看下面的代码:


comp(1,2)是我们常见的函数的写法,但它的本质是是一个类重载了operator()后表现出来的类似于函数的特性。仿函数实现起来也相当简单,只要理解了它的实质就能很快上手

但是仿函数和构造函数容易搞混,一定要注意仿函数是要针对已创建的对象调用而不是针对类来调用,那种写法是构造函数而不是仿函数

(2)优先级队列

优先级队列的功能很简单,就是结合vector、仿函数实现堆,核心代码就是AdjustUp和AdjustDown。

建议将AdjustUp和AdjustDown放进private,对外只提供push、pop这样的接口,体现封装的特性。

注意当仿函数是less时默认是大堆,greater默认是小堆,在我们进行数值比较时要注意谁在前谁在后,因为顺序不同,会影响返回值,从而影响我们生成的堆的类型。

由于堆相关的知识前面我已经详细讲过,这里就不多阐述了。

完整代码如下:


namespace my_priority_queue
{template<typename T>class less{public:bool operator()(const T& t1, const T& t2){return t1 < t2;}};	template<typename T>class greater{public:bool operator()(const T& t1, const T& t2){return t1 > t2;}};template<typename T, class Container = vector<T>, class Compare = less<T>>class priority_queue{public:priority_queue() = default;template<typename iterator>priority_queue(iterator begin, iterator end){while (begin != end){_con.push_back(*begin);begin++;}for (int parent = (int)(size() - 2) / 2; parent >= 0; parent--){AdjustDown(parent);}}size_t size(){return _con.size();}void push(const T& val){_con.push_back(val);AdjustUp(size() - 1);}void pop(){std::swap(_con[0], _con[size() - 1]);_con.pop_back();AdjustDown(0);}const T& top(){return _con[0];}bool empty(){return _con.empty();}void swap(priority_queue& p){std::swap(_con, p._con);}private:void AdjustUp(size_t child){Compare comp;size_t parent = (child - 1) / 2;while (child > 0){if (comp(_con[parent], _con[child]))std::swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}}void AdjustDown(size_t parent){Compare comp;size_t child = parent * 2 + 1;while (child < size()){if (child + 1 < size() && comp(_con[child], _con[child + 1]))child++;if(comp(_con[parent], _con[child]))std::swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}}private:Container _con;};
}

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

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

相关文章

【独家揭秘】视频号矩阵系统源码,智能多平台管理,发布效率飙升的秘密武器!

在如今这个信息爆炸的时代&#xff0c;视频内容已经成为人们获取信息和娱乐的重要方式。然而&#xff0c;对于众多内容创作者和企业来说&#xff0c;如何高效地将视频内容发布到各大平台&#xff0c;提升品牌曝光度和用户互动&#xff0c;一直是一个头疼的问题。今天&#xff0…

京东商品历史价格查询

当前资料来源于网络&#xff0c;禁止用于商用&#xff0c;仅限于学习。 下载京东APP 登录后 打开商品详情就可以看到 要获取京东商品的历史价格&#xff0c;你可以在京东网站上搜索该商品&#xff0c;并进入该商品的详情页面。然后&#xff0c;在页面中找到“商品详情”一栏&…

Oracle基础以及一些‘方言’(二)

1、Oracle的查询语法结构 Oracle 的单表查询的语法结构&#xff1a; SELECT 1 FROM 2 WHERE 3 GROUP BY 4 HAVING 5 ORDER BY 6 其每个关键词的功能与MySQL中的功能已知&#xff0c;不过分页查询的关键词 limit 并不在Oracle的语法结构中。伪列&#xff1a; 在 Oracle 的表的使…

羊大师:暑期不“胖”秘籍:羊奶滋养,细嚼慢咽是关键!

夏日炎炎&#xff0c;假期悠长&#xff0c;如何在享受悠闲时光的同时&#xff0c;保持轻盈体态&#xff0c;成了许多人心中的小秘密。今天&#xff0c;就让我们一起揭秘暑期不“胖”的秘籍&#xff0c;让羊奶的滋养与细嚼慢咽的智慧&#xff0c;成为你美丽夏日的守护神。 羊奶轻…

4.2 存储管理

大纲 页式存储必考&#xff0c;段式存储看运气 页式存储 概念

100+大屏模板,基于Vue 国产开源 IoT 物联网 Web 组态可视化 BI 数据分析工具

项目源码&#xff0c;文末联系小编 01 DataEase 可视化大屏 DataEase 是一个国产开源的数据可视化分析工具(BI工具)&#xff0c;旨在帮助用户快速分析数据并洞察业务趋势&#xff0c;以实现业务的改进与优化。它支持丰富的数据源连接&#xff0c;包括OLTP和OLAP数据库、数据仓库…

Spark RDD优化

Spark RDD优化 一、分区优化二、持久化优化三、依赖优化四、共享变量优化五、提交模式与运行模式优化六、其他优化 一、分区优化 分区数调整&#xff1a;RDD的分区数可以通过repartition和coalesce方法进行调整。合理的分区数可以提高并行度&#xff0c;但过多的分区会增加管…

捷配PCB 6个PCB板材关键参数解读技巧

PCB板材是指覆铜基板&#xff0c;是制造电路板的最主要材料。 板材的一些关键性能参数对电路板的生产加工、元器件贴装焊接、电子产品的功能实现以及产品的使用环境或寿命等都将产生一定程度的影响&#xff0c;所以掌握板材的关键参数在实际应用中非常有必要。 PCB板材的关键性…

Nifi内置处理器Processor的开发

Nifi-Processor自定义开发的流程 之前说过&#xff0c;大部分的数据处理&#xff0c;我们可以基于ExcuseGroovyScript处理器&#xff0c;编写Groovy脚本去完成&#xff08;或者Jpython&#xff0c;Js脚本等对应的组件&#xff09;&#xff0c;只能说这是基于Nifi平台的使用层面…

UML建模案例分析-时序图和类图的消息传递

概念 类图和时序图之间的交互是通过消息&#xff0c;即成员函数的调用体现的。但要遵循一定的原则&#xff0c;可参见&#xff1a; 面向对象原则之一&#xff0c;面相对象原则之二。 例子 一个电子商务系统&#xff0c;会员可通过电子商务系统购买零件。具体功能需求如下&am…

【中项第三版】系统集成项目管理工程师 | 第 4 章 信息系统架构⑤ | 4.8 - 4.9

前言 第4章对应的内容选择题和案例分析都会进行考查&#xff0c;这一章节属于技术相关的内容&#xff0c;学习要以教材为准。本章分值预计在4-5分。 目录 4.8 云原生架构 4.8.1 发展概述 4.8.2 架构定义 4.8.3 基本原则 4.8.4 常用架构模式 4.8.5 云原生案例 4.9 本章…

如何解决英国Facebook直播网络延时问题?

许多商家在英国进行Facebook直播&#xff0c;但网络延时和卡顿问题常常困扰着用户。这不仅影响观众的观看体验&#xff0c;也会给商家带来巨大损失。本文将探讨解决英国Facebook直播网络延时和卡顿问题的方案&#xff0c;以促进业务发展并提升用户满意度。 海外直播的挑战 海外…

【Flask从入门到精通:第一课:flask的基本介绍、flask快速搭建项目并运行】

从0开始入手到上手一个新的框架&#xff0c;应该怎么展开&#xff1f;flask这种轻量级的框架与django这种的重量级框架的区别&#xff1f;针对web开发过程中&#xff0c;常见的数据库ORM的操作。跟着学习flask的过程中&#xff0c;自己去学习和了解一个新的框架&#xff08;San…

unity中我想实现现实中琴弦的那种互动抖动效果,谈谈思路。

&#x1f3c6;本文收录于《CSDN问答解惑》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&…

BouncyCastleProvider 对 X.509 证书的生成

文章目录 前言BouncyCastleProvider 对 X.509 证书的生成1. demo 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&#xf…

程序员学CFA——经济学(六)

经济学&#xff08;六&#xff09; 国际贸易与资本流动国际贸易相关术语开放/封闭经济自由贸易/贸易保护贸易比价国内生产总值与国民生产总值 国际贸易的利弊分析益处弊端 从贸易中获益&#xff1a;比较优势比较优势和绝对优势比较优势的来源 贸易限制和贸易保护施行贸易保护政…

如何快速找车?一文教你如何打造一个高效的停车场反向寻车系统?

在当今快速发展的城市化进程中&#xff0c;大型商业综合体、购物中心和办公楼的停车场规模日益庞大&#xff0c;车辆数量急剧增加。随之而来的是车主在这些大型停车场中寻找自己车辆的困难。由于停车场空间大、结构复杂&#xff0c;缺乏有效的参照物&#xff0c;车主常常在寻车…

基于SpringBoot的网上书城管理系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;Java技术&#xff0c;基于SpringBoot框架 工具&#xff1a;Eclipse&#xff0c;MySQL 系统展示 首…

英福康INFICON FabGuard传感器集成与分析系统PPT

英福康INFICON FabGuard传感器集成与分析系统PPT

VS安装Qt扩展工具

1-Visual Studio中安装QT插件 **插件下载地址&#xff1a;**http://download.qt.io/development_releases/vsaddin/ 关闭VS,双击下载的QT插件&#xff0c;默认安装即可&#xff1b; &#xff08;1&#xff09;配置Qt的MSVC编译器安装路径 打开Visual Studio&#xff0c;在菜单栏…