STL容器适配器以及仿函数的简单认识

news2024/10/5 14:25:19
在学c++的过程中,我们必不可少的一大工具就是STL,并且要一定程度的了解STL背后的原理。
今天我们来探讨一下STL中stack和queue的容器适配器,以及priority_queue是什么,以及一点仿函数的知识。

1.容器适配器

1). 容器适配器

  在我们了解STL中栈和队列或者模拟实现相似的栈和队列时,在翻阅STL相关文件时,不免会碰到如下东西:
在这里插入图片描述
  左边的class T我们认识那是模板参数,实例化对象的时候会用到,但是右边的那一坨是什么东西呢?我们在平常使用中从来没有用到过。
但是看起来他也应该是一个模板参数,那就说明,在写stack的类模板的时候也会用到他,至于右边的deque是什么,我们待会再说。
  container的意思是容器。在这里插入图片描述
  容器是我们STL中六大部件中的一个,我们所了解的list,vector都是容器,容器顾名思义就是存储数据的东西。只不过每个容器存储数据的方式有所不同,而对于stack来说,他的容器可以是vector,或者list,因为这两个容器的特性都可以满足stack,所以在这里我们假如自己要写一个stack,我们容器的选择可以是这两者中的一个。那我们就可以这么写。

template <class T>
class stack {
	typedef vector<T> Container;
public:
	//.....
private:
		Container _con;
};

  他的理念就是使用vector来作为我们stack的存储数据的一种容器以便于我们实现stack的各种功能及特性。那我们也可以使用list作为容器。
  但是如果这么写的话显然需要我们再写一个list作为容器的stack,浪费时间,所以就有了容器适配器,他的写法如下:

	template <class T, class Container = deque<T>>
	class stack {
	public:
		//...
	private:
		Container _con;
	};

  那当我们在实例化的时候就可以实例化自己想要的存储容器了。

stack<int, vector<int>> st1;
stack<int, list<int>> st2;

  那我们想要模拟实现一个stack可就便捷多了。
代码如下:

namespace xxx {

	template <class T, class Container = deque<T>>
	class stack {
	public:

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

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

		T& top()
		{
			return _con.back();
		}

		const T& top()const
		{
			return _con.back();
		}

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

		bool empty()const
		{
			return _con.empty();
		}
	private:
		Container _con;
	};
}

  这个类模板的容器似于缺省值,不填写的话默认使用这里的容器。

2). deque

  deque也是STL中的一个容器,他叫双端队列。
在这里插入图片描述
在这里插入图片描述
  可以看到他支持vector的随机访问,也有list的头插头删

deque的大致实现原理

  他的原理有一点复杂,他先是有一个数组,这个数组的元素的类型是指针。这个指针指向的内容是一个大小为十(不等)的数组。deque并不是真正连续的空间,而是由一段段连续的小空间拼接而成的。
大致如下图:

在这里插入图片描述
  他会使用这样的数组来维护许多小但连续的数组,并且这个指针数组的元素,他是从中间开始向两边扩散的,假如我们头插deque,最前面的数组指针所指向的数组满了,那我们就需要开辟一个新的小数组,并且在指针数组中插入指向这个小数组的数组指针。并且这个头插的元素是在小数组的最后一个位置。他的尾插即相反。这种方式,就导致deque的迭代器难以实现。
  这样的设计会使得假如我们要删除中间的一个元素那就会使得我们移动元素非常麻烦。
  但是当我们进行头尾操作时,我们可以做到是O(1)的复杂度,并且随机访问也是趋近于O(1)。这样的特性非常适合stack和queue,所以会让他俩的默认容器为deque。

2. priority_queue

他的名字叫优先级队列,但是他的底层本质上是堆。他也需要容器适配器。
在这里插入图片描述
那知道是堆之后他的模拟实现也很简单。
代码如下:

namespace xxx
{
    template <class T>
    class Less
    {
    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:
        priority_queue()
        {}

        template <class InputIterator>
        priority_queue(InputIterator first, InputIterator last)
        {
            while (first < last)
            {
                push(*first++);
            }
        }

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

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

        const T& top() const
        {
            assert(c.size() > 0);

            return c.front();
        }

        void push(const T& x)
        {
            c.push_back(x);
            adjust_up(c.size() - 1);
        }

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

    private:

        void adjust_up(size_t child)
        {
            size_t parent = (child - 1) / 2;

            while (child > 0)
            {
                //if (c[parent] < c[child])
                if (comp(c[parent], c[child]))
                    swap(c[parent], c[child]);
                else
                    break;

                child = parent;
                parent = (child - 1) / 2;
            }
        }

        void adjust_down(size_t parent)
        {
            size_t child = parent * 2 + 1;

            while (child < c.size())
            {
                if (child + 1 < c.size() && comp(c[child], c[child + 1]))
                    child++;

                if (comp(c[parent], c[child]))
                    swap(c[parent], c[child]);
                else
                    break;

                parent = child;
                child = child * 2 + 1;
            }
        }

        Container c;

        Compare comp;

    };

};

但是我们发现,他多了一个成员Compare类型的,那这又是什么呢?这就是仿函数。

3.仿函数

  在上面我们可以看到优先级队列中模板参数不仅有类型,适配器,还有一个什么比较。比较我们知道,在堆中大小堆的比较方式是不同的。而我们在上面的实现中有有这么一个东西:
在这里插入图片描述
  我们其实也用过这么一个相似的东西,那就是C语言里的qsort。
在这里插入图片描述
这也是一个compare,但是它是一个函数指针,这里是一个类。其实仿函数的出现一部分原因就是为了取缔C语言中的函数指针,因为这东西太恶心了。
在这里插入图片描述
相反,仿函数书写简单、好调用。也使得回调函数相关的书写变得简单。
那关于仿函数的简单使用几乎和我们普通的函数调用一样,不过作为仿函数的类,都必须重载 operator() 运算符。因为调用仿函数,实际上就是通过类对象调用重载后的 operator() 运算符。

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

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

相关文章

React添加文件路径时使用@符号代替src目录(非creae-react-app)

在其它项目中看到的可以用符号来代替src目录&#xff0c;那么在自己的react项目中也必须得尝试一下。本人的项目不是通过create-react-app脚手架来创建的&#xff0c;无法使用craco或者的方案来实现。 jsconfig.json配置 用的vscode进行开发&#xff0c;查看项目当中是否存在js…

与HTTP相关的各种协议

TCP/IP TCP/IP协议是目前网络世界“事实上”的标准通信协议&#xff0c;实际上是一系列网络通信协议的统称&#xff0c;其中最核心的两个协议是 TCP和IP&#xff0c;其他的还有 UDP、ICMP、ARP 等等&#xff0c;共同构成了一个复杂但有层次的协议栈。 这个协议栈有四层&#x…

Nginx:动静分离(示意图+配置讲解)

示意图&#xff1a; 动静分离 动静分离是指将动态内容和静态内容分开处理的一种方式。通常&#xff0c;动态内容是指由服务器端处理的&#xff0c;例如动态生成的网页、数据库查询等。静态内容是指不需要经过服务器端处理的&#xff0c;例如图片、CSS、JavaScript文件等。通过…

C++之make_unique、namespace、class类总结(二百四十二)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 人生格言&#xff1a; 人生…

React-Router-6学习笔记

一、新建react项目 1、新建项目命令&#xff1a; yarn create vite react-router --template react 2、在vsCode中打开项目 3、在vsCode打开命令终端&#xff0c;输入 yarn 4、执行yarn dev启动当前项目 yarn dev 5、删除多余的东西&#xff0c;保留app.jsx和main.jsx文…

高校教务系统登录页面JS分析——皖西学院

高校教务系统密码加密逻辑及JS逆向 本文将介绍皖西学院教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文&#xff0c;你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习&#xff0c;勿用于非法用途。 一、密…

NLP算法面经 | 腾讯 VS 美团

作者 | 曾同学 编辑 | NewBeeNLP 面试锦囊之面经分享系列&#xff0c;持续更新中 后台回复『面试』加入讨论组交流噢 lz从3月初脚因打球扭伤了开始&#xff0c;投递简历&#xff0c;接二连三的面试鞭尸又面试&#xff0c;昨天才终于上岸了&#xff0c;分享经验~ 腾讯PCG看点&…

SSH 基础学习使用

什么是SSH 1.SSH SSH&#xff08;Secure Shell&#xff09; 是较可靠&#xff0c;专为远程登录会话和其他网络服务提供安全性的协议&#xff0c;利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。 实际应用中&#xff0c;主要用于保证远程登录和远程通信的安全&#…

数字技术助力智慧公厕,让公厕变身为全新创新应用

在如今数字化的时代&#xff0c;数字技术的集成应用已经渗透到了生活的方方面面。其中一个令人瞩目的领域就是智慧公厕。以前只是简单的厕所&#xff0c;如今借助数字技术的力量&#xff0c;智慧公厕变得功能强大、智能高效。接下来&#xff0c;我们将以智慧公厕源头领航厂家广…

Retrieve Anything To Augment Large Language Models

简介 论文主要介绍了一套通过对比学习和蒸馏学习的方法&#xff0c;来增强学习了embedding向量&#xff0c;然后能够在知识增强&#xff0c;长上下文建模&#xff0c;ICL和工具学习等方面来增强大模型能力。

计算机网络第一章补充整理(计算机网络体系结构)

前言&#xff1a;以下整理内容&#xff0c;参考《计算机网络自顶向下》和哈工大的计网慕课 目录 计算机网络的体系结构的一些概念为什么采用分层结构&#xff1f;分层结构的优点分层结构的缺点 开放系统互连&#xff08;OSI&#xff09;参考模型物理层功能数据链路层功能网络层…

大数据flink篇之三-flink运行环境安装后续一yarn-session安装

前提&#xff1a; Hadoop 必須保证在 2.2 以上&#xff0c;且必須裝有 hdfs 服务。Hadoop安装后续会有相关说明。 具体的&#xff0c;在生产环境中&#xff0c;flink一般会交由yarn、k8s等资源管理平台来处理。本章主要讲解yarn模式下的session cluster模式。 flink Session-C…

FPC柔性电路板介绍及PCB设计经验规则总结

🏡《总目录》 目录 1,概述2,FPC的特点3,FPC设计十五条经验规则4,总结1,概述 FPC软板由于具有可弯曲折叠的特点,当前在消费电子,汽车电子和航空航天领域应用广泛。本文详细介绍FPC的特点并对FPC板设计中需要注意的经验原则进行总结。 2,FPC的特点 FPC的全称是Flexibl…

Python实现带图形界面的计算器

Python实现带图形界面的计算器 在本文中&#xff0c;我们将使用Python编写一个带有图形用户界面的计算器程序。这个程序将允许用户通过点击按钮或键盘输入数字和操作符&#xff0c;并在显示屏上显示计算结果。 开发环境准备 要运行这个计算器程序&#xff0c;您需要安装Pyth…

数据链路层—以太网协议

数据链路层—以太网协议 文章目录 数据链路层—以太网协议重新认识四层模型以太网局域网特点以太网帧格式碰撞领域和避免碰撞算法认识MAC地址令牌环网交换机认识MTUMTU对IP协议的影响MTU对UDP协议的影响MTU对TCP协议的影响数据跨网段传输的过程 重新认识四层模型 TCP/IP分层模型…

C# Convert和BitConverter类学习

前言&#xff1a; C# Convert是一个比较好用的强制转换&#xff0c;相比我们之前用的(int)或者是类型.Parse()&#xff0c;Convert给我们提供了很多的选项&#xff0c;特别是对于有字节要求的变量&#xff0c;Convert简直就是C#编程的福音&#xff0c;BitConvert对于byte数组转…

数据结构的奥秘:算法与实际应用的完美融合

文章目录 第一部分&#xff1a;数据结构的精髓1. 数组&#xff08;Array&#xff09;2. 链表&#xff08;Linked List&#xff09;3. 栈&#xff08;Stack&#xff09;和队列&#xff08;Queue&#xff09;4. 树&#xff08;Tree&#xff09;5. 图&#xff08;Graph&#xff09…

fastjson 1.2.47 远程命令执行漏洞

fastjson 1.2.47 远程命令执行漏洞 文章目录 fastjson 1.2.47 远程命令执行漏洞1 在线漏洞解读:2 环境搭建3 影响版本&#xff1a;4 漏洞复现4.1 访问页面4.2 bp抓包&#xff0c;修改参数 5 使用插件检测漏洞【FastjsonScan】5.1使用説明5.2 使用方法5.2.1 右键菜单中&#xff…

车载电子电器架构 —— 国产基础软件生态简介

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…

python二次开发CATIA:测量曲线长度

以下代码是使用Python语言通过win32com库来控制CATIA应用程序的一个示例。主要步骤包括创建一个新的Part文件&#xff0c;然后在其中创建一个新的几何图形集&#xff0c;并在这个集合中创建一个样条线。这个样条线是通过一组给定的坐标点来创建的&#xff0c;这些点被添加到集合…