【C++】 STL(下)算法、迭代器、容器适配器 和 仿函数

news2024/11/26 22:25:44

文章目录

      • 算法
      • 迭代器
      • 容器适配器
        • 栈(stack)
        • 队列(queue)
      • 仿函数

算法

STL中的算法头文件位于和文件中(以为主)

  1. for_each(InputIterator First,InputIterator Last,Function _Func); 遍历,具体做什么事取决于第三个方法参数。
void show(int a) {
	cout << a << "  ";
}
void show1(int &a) {
	if (a % 2 == 1) {
		a += 1;
	}
}
	vector<int> vec{ 1,2,3,4 };
	//遍历
	::for_each(vec.begin(), vec.end(), &show); cout << endl;
	//如果是奇数就+1
	::for_each(vec.begin(), vec.end(), &show1);
	::for_each(vec.begin(), vec.end(), &show); cout << endl;
  1. count(InputIterator First,InputIterator Last,const Type& Val),统计指定范围内的元素的数量。
	list<int> lst{ 5,1,1,6,1,0,1 };
	cout << ::count(lst.begin(), lst.end(), 1) << endl;  //4

	cout << ::count(lst.begin(), --lst.end(), 1) << endl;  //3
  1. bool equal(InoutIterator First1,InputIterator Last1,InputIterator First2),比较First1Last1范围内的元素的值,与起始的First2诸葛比较是否相等。相等返回true,否则返回false。First容器元素数不能小于First1Last1。
	list<char> lst2{ 1,2,3,4 };
	list<char> lst3{ 1,2,3,4,5 };

	cout << ::equal(lst2.begin(), lst2.end(), lst3.begin()) << endl;  //1

	list<char> lst4{ 0,1,2,3,4,5 };
	cout << ::equal(lst2.begin(), lst2.end(), ++lst4.begin()) << endl;  //1
  1. InputIterator find(InputIterator First,InputIterator Last,const Type& Val)。范围查找元素,如果找不到返回Last
	vector<int>::iterator ite = ::find(vec.begin(), vec.end(), 6);
	if (ite != vec.end()) {
		cout << *ite << endl;
	}
	else {
		cout << "没找到" << endl;
	}
  1. void sort(RandomAccessIterator first,RandomAccessIterator last,Predicate comp);不能对链表进行排序,链表自带了sort功能函数,map、set会自动排序。
	vector<int> vec3{ 5,1,3,0 };

	::sort(vec3.begin(), vec3.end(), greater<>());  //降序
	::for_each(vec3.begin(), vec3.end(), &show);
	cout << endl;

	::sort(vec3.begin(), vec3.begin()+2, less<>());  //升序
	::for_each(vec3.begin(), vec3.end(), &show);
	cout << endl;
  1. const Type& max(const Type&Left,const Type& Right);返回相比最大的容器,是复制一份。
	vector<int> vec4{ 3,6 };

	vector<int> v1 = ::max(vec4, vec3);
	::for_each(v1.begin(), v1.end(), &show);  //3  6
  1. const Type& min(const Type&Left,const Type& Right);返回相比最小的容器,是复制一份。
void show2(pair<string,int> pr) {
	cout << pr.first << "-" << pr.second << endl;
}
	map<string, int>  m1{ {"12",10} };
	map<string, int>  m2{ {"12",11} };

	map<string, int> m = ::min(m1, m2);
	::for_each(m.begin(), m.end(), &show2); cout << endl;

键值优先比较,简直相同比较实值

	map<string, int> m3{ {"11",11} };  

	map<string, int> mm = ::min(m1, m3);
	::for_each(mm.begin(), mm.end(), &show2); cout << endl;

迭代器

算法-迭代器-容器之间的关系:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RtH46V2J-1686745450614)(C++.assets/image-20230612155538575.png)]

用正常迭代器遍历链表:

	list<int> lst{ 1,2,3,4 };
	list<int>::iterator ite = lst.begin();
	while (ite != lst.end()) {
		cout << *ite << "  ";
		ite++;
	}
	cout << endl;

那现在我们想要反着去遍历我们该怎么办呢?

正常的思路就是我们让迭代器指向尾,然后如果不等于头就减减

	ite = lst.end();
	while (ite != lst.begin()) {
		cout << *--ite << "  ";
		//ite--;
	}
	cout << endl;

注意:因为尾节点没有实际意义,所以不能先取值再减减,可以在取值的同时加上一个左减减,这样每次输出的就是迭代器指向的前一个节点的值,同时也避免了取不到头节点的现象。

那么以上的例子不是真正意义上的反向迭代器,下面我们就来看真正的反向迭代器。

反向迭代器:reverse_iterator,rbegin(),反向的头,rend(),反向的尾。

reverse_iterator::base(),反向迭代器转正向迭代器。

	list<int>::reverse_iterator revIte = lst.rbegin();  //定义一个反向迭代器指向反向的头
	while (revIte != lst.rend()) {
		cout << *revIte << "  ";
		revIte++;
	}cout << endl;

在删除节点时,函数中只能传入正向迭代器,所以要将反向迭代器转为正向迭代器,并且转正后会向后偏移一位,所以要对迭代器进行左减减操作,然后用正常迭代器接一下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mnGmFSJa-1686745450615)(C++.assets/image-20230612161416970.png)]

	revIte = lst.rbegin();  
	while (revIte != lst.rend()) {
		if (*revIte == 2) { //匹配后,删除节点
			ite = --revIte.base();  //反向迭代器转为正向迭代器,转正后会向后偏移一位

			cout << "转正后:" << *ite << endl;

			lst.erase(ite);
			break;
		}
		revIte++;
	}cout << endl;

容器适配器

容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素。容器适配器本质上还是容器,只不过此容器模板类的实现,利用了大量其他基础容器模板类中已经写好的成员函数。当然也可以添加新的成员,他是一个封装了序列行容器的模板类,他在一般序列容器的基础上提供了一些不同的功能。之所以称为适配器类,是因为它可以通过适配器现有的接口来提供不同的功能,将不适用的序列式容器(包括vector、deque和list)变得适用。容器适配器不支持迭代器、当然也就不能使用算法(algorithm)函数。

注意:容器适配器默认都是用底层序列性容器实现的。

容器适配器主要包括:stack栈适配器、queue队列适配器。

栈(stack)

实现的是一个后入先出(Last-In-First-Out,LIFO)的压入栈。它默认是用deque<_Ty>去实现的,但也可以用list vector等底层容器实现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pAGZk7fn-1686745450616)(C++.assets/image-20230612163646518.png)]

	stack<int> st;
	st.push(1);
	st.push(2);
	st.push(3);
	st.push(4);

	cout << "size = " << st.size() << endl;

	while (!st.empty()) {
		cout << st.top() << "  ";  //查看栈顶元素的值
		st.pop();  //栈顶出战
	}
	cout << endl;
	cout << "size = " << st.size() << endl;

队列(queue)

特点:实现的是一个先入先出(First-In-First-Out,FIFO)的队列,它默认是用deque<_Ty>去实现的,但也可以用list等底层容器实现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wDXcGVxH-1686745450616)(C++.assets/image-20230612163936055.png)]

	queue<int> que;
	que.push(1);
	que.push(2);
	que.push(3);
	que.push(4);

	cout << "front = " << que.front() << "   back = " << que.back() << endl;
	cout << "size = " << que.size() << endl;
	while (!que.empty()) {
		cout << que.front() << "  ";
		que.pop();
	}
	cout << endl;
	cout << "size = " << que.size() << endl;

仿函数

仿函数的通俗定义:仿函数(functor)又称为函数对象(function object)是一个能行使函数功能的类。仿函数的语法几乎和我们普通函数调用一样,不过作为仿函数的类,都必须重载operator()运算符。

先来写一个真函数:

int add(int a, int b) {
	return a + b;
}
cout << add(10, 20) << endl;

仿函数:

class CAdd {  //仿函数: 有状态的函数
public:
	int sum;
	CAdd():sum(0){}

	int operator() (int a, int b) {
		sum += a + b;
		return a + b;
	}
};
	CAdd Add;
	cout << Add(10, 30) << endl;

	cout << Add(40, 50) << endl;

	cout << "sum = " << Add.sum << endl;

仿函数的优势:它是有状态的函数,他也有类的特性,除了可以增加成员函数外还可以增加成员属性,就像上面的我们增加一个sum用来记录每次加的结果后累加。

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

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

相关文章

电影《天空之城》观后感

上周看了电影《天空之城》这部电影&#xff0c;这部电影是六一儿童节时上映的&#xff0c;本周也算是补票吧&#xff0c;童年时&#xff0c;看的都是免费的&#xff0c;早已经忘记是在哪里看到的&#xff0c;但当时对自己触动很大&#xff0c;算是启蒙电影&#xff0c;所以今天…

【RabbitMQ教程】第二章 —— RabbitMQ - 简单案例

&#x1f4a7; 【 R a b b i t M Q 教程】第二章—— R a b b i t M Q − 简单案例 \color{#FF1493}{【RabbitMQ教程】第二章 —— RabbitMQ - 简单案例} 【RabbitMQ教程】第二章——RabbitMQ−简单案例&#x1f4a7; &#x1f337; 仰望天空&#xff0c;妳我亦是行人…

汽车电子Autosar之以太网SOMEIP

前言 首先&#xff0c;请问大家几个小小问题&#xff0c;你清楚&#xff1a; 你知道什么是SOME/IP吗&#xff1f;你知道为什么会产生SOME/IP即相关背景吗&#xff1f;你知道SOME/IP与SOA又有着哪些千丝万缕的联系呢&#xff1f;SOME/IP在实践中到底应该如何使用呢&#xff1f…

QuickList

基本概述 ZipList虽节省内存但是申请内存必须是连续的&#xff0c;如果内存占用很大&#xff0c;申请内存效率就会很低&#xff0c;可以限制ZipList长度和entry大小&#xff1b; 实在要存储大量数据&#xff0c;超出ZipList最佳上限了&#xff0c;此时可以创建多个ZipList来分片…

Autosar诊断实战系列04-基于CAPL语言的通信类诊断测试脚本开发

本文框架 前言1.CAPL编程简单介绍2. CAPL脚本开发实战2.1 添加CAPL Test Module2.2 CAPL脚本实战编写前言 在本系列笔者将结合工作中对诊断实战部分的应用经验进一步介绍常用UDS服务的进一步探讨及开发中注意事项, Dem/Dcm/CanTp/Fim模块配置开发及注意事项,诊断与BswM/NvM关…

OpenAI官方提示词课(五)如何进行文本翻译校正修改

在本篇文章中&#xff0c;我们将探讨如何使用大语言模型进行文本转换任务&#xff0c;例如语言翻译、拼写和语法检查、语气调整和格式转换。 翻译 ChatGPT接受多种语言的训练&#xff0c;使得模型具备翻译能力。以下是如何使用这种能力的一些示例。 prompt f""&q…

利用lambda优化反射功能实现方法调用

最近在思考lambda相关的问题&#xff0c;简单记录下做的相关反射替代和函数映射的尝试。 原理分析 lambda是jdk8才提供的&#xff0c;原理其实就是动态生成内部类来执行函数映射的方法。也就是说一段lambda表达式会对应特定的类方法&#xff0c;之后调用。底层是通过LambdaMe…

《离散数学》:逻辑

〇、前言 离散数学是数学的一个分支&#xff0c;研究离散对象和离散结构的数学理论和方法。这学期学校开了离散数学的课程&#xff0c;我受益颇丰&#xff0c;感觉到了离散数学真正的魅力&#xff0c;也被开创离散数学各个分支的人的聪明与才智深深折服。与连续数学不同&#…

Stopwatch工具类计时器探究

搬砖的我们 特别是Java开发的童鞋们, 经常需要通过记录开始时间和结束时间&#xff0c;然后通过计算差值&#xff0c;得到时间差&#xff0c;如下面的代码&#xff1a; long start System.currentTimeMillis(); long end System.currentTimeMillis(); System.out.println(…

【数字调制】数字调制技术FSK与PSK分析与研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

栈的数据结构完成表达式(5*10+2-7+5)/10+5的计算

栈&#xff08;Stack&#xff09;是一种线性数据结构&#xff0c;具有后进先出&#xff08;LIFO&#xff09;的特性。它可以理解为一种类似于抽屉的容器&#xff0c;只能在顶部进行插入和删除操作&#xff0c;其他位置不可访问。栈的基本操作包括入栈&#xff08;push&#xff…

[数字图像处理]第五章 图像复原与重建

文章目录 第五章 图像复原与重建5.1图像退化复原过程的模型图像退化图像复原图像复原与图像增强图像退化的数学模型为什么采用线性位移不变系统模型来描述图像退化过程 5.2 噪声模型x5.2.1 噪声的空间和频率特性5.2.2 一些重要的噪声概率密度函数高斯噪声实验&#xff1a;采用高…

【微服务架构设计和实现】4.1 微服务架构概述和设计原则

往期回顾&#xff1a; 第一章&#xff1a;【云原生概念和技术】 第二章&#xff1a;【容器化应用程序设计和开发】 第三章&#xff1a;【基于容器的部署、管理和扩展】 4.1 微服务架构概述和设计原则 4.1 微服务架构概述和设计原则4.1.1 微服务架构的优点4.1.2 微服务架构遵…

在 ArcGIS Pro 中使用 H3 创建蜂窝六边形

在 ArcGIS Pro 中使用 H3 创建蜂窝六边形https://mp.weixin.qq.com/s/tGk7AT2jAcvsmNyp2bRvig 之前看了个有意思的ArcGIS博客&#xff1a;H3六边形&#xff0c;当然了这也不是个新鲜东西了。原文&#xff1a; https://www.esri.com/arcgis-blog/products/arcgis-pro/analytic…

为什么要学GIS开发

什么是地理信息系统技术&#xff1f; GIS技术使用专门的计算机系统来获取地理数据并将其集成到智能“超级”地图中。然后&#xff0c;这些数据可用于创建无穷无尽的“假设”场景&#xff0c;为以下应用程序提供强大的工具&#xff1a; 制图&#xff08;地图制作&#xff09;应…

【阅读随笔】Rewrite-Based Decomposition of Signal Temporal Logic Specifications

文章目录 Overview1 IntroLTL任务分解STL任务分解本文工作 Background and Problem DefinitionSTLAgent假设与问题方法 An STL Rewriting SystemRewriting SystemFormula Rewrite DAG Decomposing STL智能体编队任务分解最优分解 Exploring the Formula Rewrite DAGExperiments…

soci在windows下vs2010编译

需要下载 的资源 mysql connector c 因为其使用的的是mysql connector c的api&#xff0c;需要下载https://downloads.mysql.com/archives/c-c/ 分别对应32位和64位的 soci 4.0 从github上下载4.03分支 https://github.com/SOCI/soci/tree/v4.0.3 cmake 需要下载3.25版…

Java多线程快速入门

文章目录 Java多线程快速入门1、认识多线程2、多线程的实现2.1 继承Thread类2.2 实现Runnable接口2.3 利用Callable和Futrue接口2.4 三种方式的比较 3、Thread类常用API3.1 守护线程3.2 礼让线程3.3 插入线程3.4 线程的生命周期 5、线程安全问题5.1 synchronized5.2 Lock 6、等…

wsl安装ubuntu并设置gnome图形界面详细步骤(win11+ubuntu18)

0.前言 wsl确实是个好东西&#xff0c;不过之前配了好几次都没有成功&#xff0c;因为wsl本身确实是有bug。当时配的时候查到GitHub上的一个issue还没被修好。现在重新配一下。 我的环境是Windows11家庭版。区别于win10&#xff0c;win11安装完默认就是wsl2。 1.下载 首先打…

Linux之管理联网

目录 Linux之管理联网 rhel8与7的区别 NetworkManager 定义 NM能管理各种网络 使用方法 使用NM的原因 nmcli使用方法 nmcli的两个常用命令 nmcli connection 定义 两种状态 nmcli device 定义 四种状态 nmcli常用命令 查看ip&#xff08;类似于ifconfig、ip addr&a…