C++ stack and queue

1. stack模拟实现


C++STL中的栈是一种容器适配器,它是将vector/list进行封装,push/pop等接口直接调用vector/list的接口即可,不需要像C语言那样,从头开始造轮子

namespace byh
{template<class T, class Container = deque<T>>class stack{public:void push(const T& val){_con.push_back(val);}void pop(){_con.pop_back();}const T& top(){return _con.back();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}int main()
{byh::stack<int> st;st.push(1);st.push(2);st.push(3);st.push(4);while (!st.empty()){cout << st.top() << " ";st.pop();}cout << endl;return 0;
}

在模板实例化时,我们给栈传什么容器,它就调用该容器的接口,默认容器是deque

deque是一种双端队列,它结合了vectorlist 的优势

vector

  • 优势:能够随机访问
  • 劣势:头插/删,中间插/删要挪动数据,效率低;扩容有消耗

list

  • 优势:任意位置插入/删除效率高
  • 劣势:不支持随机访问

可以说,vectorlist是两个互补的容器,既然这样,能不能把这两个容器的优势结合;因为有这样的需求,就有了deque

它的底层会有一个中控指针数组,每个元素都指向一个长度为N的数组

尾插时,如果当前的所有数组都满了,则开辟新的指针,指向新的数组,插入元素

头插时,在数组中,以从后往前的顺序依次插入元素

访问第i个元素时,如果第一个数组没满,i减去第一个数组元素个数,进行下面的运算:

  • i / N -->找到该元素在第几个数组
  • i % N -->找到是在该数组的第几个元素

如果第一个数组满了,直接进行上面的运算

如果中控指针数组满了,进行扩容,虽然最总还是要扩容,但消耗上大大降低

deque

  • 优点:头插/删,尾插/删效率都不错
  • 缺点:中间插/删会比较麻烦,不如list;随机访问的效率不如vector

stackqueue的默认容器使用deque的原因就在于它的头插/删,尾插/删效率可以,并且不会使用随机访问或者中间插/删

2.queue模拟实现


namespace byh
{template<class T, class Container = deque<T>>class queue{public:void push(const T& val){_con.push_back(val);}void pop(){_con.pop_front();}T& back(){return _con.back();}T& front(){return _con.front();}const T& back() const{return _con.back();}const T& front() const{return _con.front();}bool empty(){return _con.empty();}size_t size(){return _con.size();}private:Container _con;};
}int main()
{byh::queue<int> q;q.push(1);q.push(2);q.push(3);q.push(4);while (!q.empty()){cout << q.front() << " ";q.pop();}cout << endl;return 0;
}

3. priority_queue


queue系列中,除了先进先出的普通queue之外,还有一个优先级队列priority_queue

pop时,不再是先进先出,而是按规定的优先级取出元素

#include<iostream>
#include<queue>int main()
{std::priority_queue<int> pq;pq.push(3);pq.push(2);pq.push(4);pq.push(5);pq.push(1);while (!pq.empty()){std::cout << pq.top() << " ";pq.pop();}std::cout << std::endl;return 0;
}
// 输出 5 4 3 2 1

在这里插入图片描述

仿函数实际上是一个类,只不过我们可以用函数的方式去使用它

它的内部是对()运算符的重载

    template<class T>struct Less{bool operator()(const T& x, const T& y){return x < y;}};void Test()
{byh::Less<int> less;cout << less(1, 2) << endl;// 有名对象cout << less.operator()(1, 2) << endl;cout << byh::Less<int>()(1, 2) << endl;// 匿名对象
}

我们可以在仿函数内部控制比较的逻辑,生活中大部分场景下都是用自定义类型描述一个对象,如何控制该对象的比较,进行排序,就需要我们规定好比较方式

struct Goods
{Goods(const char* str, double price, int evaluate):_name(str),_price(price),_evaluate(evaluate){}string _name;double _price;int _evaluate;
};struct ComparePriceLess
{bool operator()(const Goods& x, const Goods& y){return x._price < y._price;}
};//...int main()
{vector<Goods> v = { {"苹果",3.1,2},{"草莓",4.2,4},{"苹果",2.6,3} };sort(v.begin(), v.end(), ComparePriceLess());return 0;
}

3.1 模拟实现

	template<class T>struct Less{bool operator()(const T& x, const T& y){return x < y;}};template<class T>struct Greater{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 AdjustUp(int child){int parent = (child - 1) / 2;Compare com;while (child > 0){if (com(_con[parent], _con[child])){swap(_con[parent], _con[child]);child = parent;parent = (child - 1) / 2;}else break;}}void push(const T& val){_con.push_back(val);AdjustUp(size() - 1);}void AdjustDown(int parent){int child = parent * 2 + 1;Compare com;while (child < size()){if (child + 1 < size() && com(_con[child], _con[child + 1]))child++;if (com(_con[parent], _con[child])){swap(_con[parent], _con[child]);parent = child;child = parent * 2 + 1;}else break;}}void pop(){swap(_con[0], _con[size() - 1]);_con.pop_back();AdjustDown(0);}T& top(){return _con[0];}const T& top() const{return _con[0];}size_t size() const{return _con.size();}bool empty() const{return _con.empty();}private:Container _con;};

4. Reverse_Iterator


反向迭代器与正向迭代器功能类似,它们都是遍历,不同的是,反向迭代器++往前走,--往后走

我们可以对正向迭代器的++--修改,但这样做,每个容器的迭代器都要进行拷贝修改,不仅代码冗余,还麻烦

于是,我们用const迭代器的思路,将Reverse_Iterator写成一个模板,我们给它传哪个容器的迭代器,编译器就帮我们形成哪个容器的反向迭代器,从而减少我们的工作量

STL中,rbegin()rend()的位置与begin()end()相反

访问时,是解引用当前位置的上一个位置

在这里插入图片描述

namespace byh
{template<class Iterator, class Ref, class Ptr>struct ReverseIterator{Iterator _it;ReverseIterator(Iterator it):_it(it){}Ref operator*(){Iterator temp = _it;return *(--temp);}Ptr operator->(){return &(operator*());}// ++itReverseIterator operator++(){_it--;return *this;}// --itReverseIterator operator--(){_it++;return *this;}bool operator!=(ReverseIterator rit){return _it != rit._it;}};
}
erator it):_it(it){}Ref operator*(){Iterator temp = _it;return *(--temp);}Ptr operator->(){return &(operator*());}// ++itReverseIterator operator++(){_it--;return *this;}// --itReverseIterator operator--(){_it++;return *this;}bool operator!=(ReverseIterator rit){return _it != rit._it;}};
}

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

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

相关文章

智慧隧道建设中,如何提升隧道广播清晰度,解决隧道广播有效发布问题

近年来&#xff0c;我国高速公路智慧隧道建设步伐加快&#xff0c;全国各地高速公路运营单位纷纷加大投资力度&#xff0c;进行智慧隧道建设&#xff0c;提高隧道智能化水平。通过高清视频监控、AI视频识别、雷视融合、全域轨迹、激光雷达、火灾报警、气体检测、亮度检测、自动…

【Scala---04】函数式编程 『 函数 vs 方法 | 函数至简原则 | 函数式编程』

文章目录 1. 函数 vs 方法1.1 方法(1) 定义方法(2) 运算符即方法 1.2 函数(1) 定义函数(2) 匿名函数 1.3 方法转为函数1.4 可变参数&默认参数 2. 函数至简原则3. 函数式编程3.1 函数式编程思想3.3 函数柯里化&闭包3.5 递归 & 尾递归 4. 补充4.1 访问元祖元素4.2 &g…

ROS机器人入门:机器人系统仿真【学习记录】——2

承接上一篇博客&#xff1a; ROS机器人入门&#xff1a;机器人系统仿真【学习记录】——1-CSDN博客 我们先前结束了&#xff08;上一篇博客中&#xff09;&#xff1a; 1. 概述 2. URDF集成Rviz基本流程 3. URDF语法详解 4. URDF优化_xacro 下面让我们继续学习ROS机器人…

【Scala---01】Scala简介与环境部署『 Scala简介 | 函数式编程简介 | Scala VS Java | 安装与部署』

文章目录 1. Scala简介2. 函数式编程简介3. Scala VS Java4. 安装与部署 1. Scala简介 Scala是由于Spark的流行而兴起的。Scala是高级语言&#xff0c;Scala底层使用的是Java&#xff0c;可以看做是对Java的进一步封装&#xff0c;更加简洁&#xff0c;代码量约是Java的一半。…

前端开发攻略---打破Chrome的最小字号限制,设置任意字号大小

目录 1、原因 2、解决方法 1、原因 由于Chrome浏览器的限制&#xff0c;在网页中的字号默认最小为12px&#xff0c;更改为12px以下的字号大小是无效的 2、解决方法 1、在Chrome浏览器中调整字号最小值 优点&#xff1a;快&#xff0c;方便&#xff0c; 缺点&#xff1a;只对自…

Delta lake with Java--在spark集群上运行程序

昨天写了第一篇入门&#xff0c;今天看见有人收藏&#xff0c;继续努力学习下去。今天要实现的内容是如何将昨天的HelloDetlaLake 在spark集群上运行&#xff0c;。具体步骤如下 1、安装spark,我使用的是 spark-3.5.1-bin-hadoop3-scala2.13&#xff0c;去官网下载&#xff0c…

全流程基于GIS、python机器学习技术的地质灾害风险评价与信息化建库应用

入门篇&#xff0c;ArcGIS软件的快速入门与GIS数据源的获取与理解&#xff1b;方法篇&#xff0c;致灾因子提取方法、灾害危险性因子分析指标体系的建立方法和灾害危险性评价模型构建方法&#xff1b;拓展篇&#xff0c;GIS在灾害重建中的应用方法&#xff1b;高阶篇&#xff1…

网络基础-思科IOS基本操作(Cisco)

思科设备的命令行模式&#xff1a; 1.用户模式 (User EXEC Mode): 这是用户最初进入设备时所处的模式。在这个模式下&#xff0c;用户只能执行一些基本的查看命令&#xff0c;不能进行任何配置更改。能够进入该模式说明设备没问题&#xff1b;提示符通常是一个设备名称后面跟着…

BetterMouse for Mac激活版:鼠标增强软件

BetterMouse for Mac是一款鼠标增强软件&#xff0c;旨在取代笨重的、侵入性的和耗费资源的鼠标驱动程序&#xff0c;如罗技选项。它功能丰富&#xff0c;重量轻&#xff0c;效率优化&#xff0c;而且完全隐私安全&#xff0c;试图满足你在MacOS上使用第三方鼠标的所有需求。 B…

【linux学习指南】linux 环境搭建

文章目录 &#x1f4dd;前言&#x1f320; 云服务器的选择&#x1f320;阿里云&#x1f320;腾讯云&#x1f320;华为云 &#x1f320;使用 XShell 远程登陆到 Linux&#x1f309;下载 XShell &#x1f320;查看 Linux 主机 ip&#x1f309; XShell 下的复制粘贴&#x1f309; …

Java 函数式编程 的基础使用2-BiConsumer

1、创建函数时&#xff0c;确定函数的参数类型和具体操作。 2、使用accept接收函数参数&#xff0c;并执行函数操作。 public class MyBiConsumer {public static void main(String[] args) {BiConsumer<String, Integer> printNameAndAge (param1, param2) -> {Sys…

FIFO Generate IP核使用——异步复位

FIFO Generator IP核提供了一个复位输入&#xff0c;当该输入被激活时&#xff0c;它会复位所有的计数器和输出寄存器。对于块RAM或分布式RAM实现&#xff0c;复位FIFO并不是必需的&#xff0c;可以在FIFO中禁用复位引脚。共有两种复位类型选项&#xff1a;异步复位和同步复位。…

FTP和NFS

一、FTP 1.FTP原理 FTP&#xff08;file Transfer Protocol&#xff0c;文件传输协议&#xff09;&#xff0c;是典型的C/S架构的应用层协议&#xff0c;由客户端软件和服务端软件两个部分共同实现文件传输功能&#xff0c;FTP客户端和服务器之间的连接时可靠的&#xff0c;面…

八股文(C#篇)

C#中的数值类型 堆和栈 值类型的数据被保存在栈&#xff08;stack)上&#xff0c;而引用类型的数据被保存在堆&#xff08;heap&#xff09;上&#xff0c;当值类型作为参数传递给函数时&#xff0c;会将其复制到新的内存空间中&#xff0c;因此在函数中对该值类型的修改不会影…

数据结构===二叉树

文章目录 概要二叉树的概念分类存储遍历前序中序后序 小结 概要 简单写下二叉树都有哪些内容&#xff0c;这篇文章要写什么 二叉树的概念分类&#xff0c;都有哪些二叉树遍历 对一个数据结构&#xff0c;最先入手的都是定义&#xff0c;然后才会有哪些分类&#xff0c;对二叉…

时代少年团MV女主被骂上热搜,时代峰峻走到了十字路口

女演员和男团拍个MV都会被骂上热搜&#xff0c;这年头粉丝都这么霸道了&#xff1f; #时代少年团女主 贺美琦# #贺美琦曾是TFBOYS的MV女主# #时代少年团MV有女主# ...... 自从时代少年团第三张专辑《叁重楼》的新歌《那些我没说的话》曝光之后&#xff0c;歌曲MV中女主角的…

开源电子邮件营销平台 listmonk 使用教程

做产品肯定要做电子邮件营销&#xff0c;特别是面向海外的产品&#xff0c;电子邮件营销已成为企业与客户沟通、建立品牌忠诚度和推动销售的重要工具&#xff0c;可以直接接触到目标受众&#xff0c;提供个性化内容&#xff0c;并以相对较低的成本获得可观的投资回报。你看&…

Vue2——前端笔记

Vue 一、Vue核心1.1、vue简介1.2、初始vue1.3、模板语法1.4、数据绑定1.5、el与data的两种写法1.6、MVVM模型1.7、Vue中的数据代理1.7.1、Object.defineProperty() 理解1.7.2、Vue中的数据代理 1.8、事件处理1.8.1、事件的基本用法1.8.2、事件修饰符1.8.3、键盘事件 1.9、计算属…

KUKA机器人KR3 R540维护保养——更换齿形带

对KUKA机器人进行维护保养&#xff0c;可以增加机器人的使用寿命&#xff0c;减少故障率。本篇文章的内容是更换KUKA机器人轴齿形带。我们知道机器人长时间运行后&#xff0c;部分轴的齿形带会发生磨损&#xff0c;张力也会发生变化&#xff0c;这时就需要更换齿形带。本篇文章…

RoNID:通过生成可靠标签与聚类友好型表征来实现新意图的发现

论文地址&#xff1a;https://arxiv.org/abs/2404.08977 原文地址&#xff1a;intents-are-not-going-away-ronid-is-a-new-intent-discovery-framework 2024 年 4 月 26 日 Robust New Intent Discovery&#xff08;RoNID&#xff09;框架致力于在开放域场景中识别已知意图并合…