C++11后的STL算法

news2024/11/13 20:46:39

文章目录

  • 一、函数对象
  • 二、预定义的函数对象
  • 三、算法函数
    • 1.自己实现foreach算法
    • 2.自己实现的findif算法
    • 3.自己实现bsort算法

一、函数对象

STL提供了很多处理容器的函数模板,它们的设计是相同的,有以下特点:
1)用迭代器表示需要处理数据的区间。
2)返回迭代器放置处理数据的结果(如果有结果)。
3)接受一个函数对象参数(结构体模板),用于处理数据(如果需要)。

很多STL算法都使用函数对象,也叫函数符(functor),包括函数名、函数指针和仿函数。

函数符的概念:
1)生成器(generator):不用参数就可以调用的函数符。
2)一元函数(unary function):用一个参数可以调用的函数符。
3)二元函数(binary function):用两个参数可以调用的函数符。
改进的概念:
1)一元谓词(predicate):返回bool值的一元函数。
2)二元谓词(binary predicate):返回bool值的二元函数。

二、预定义的函数对象

STL定义了多个基本的函数符,用于支持STL的算法函数。

包含头文件:#include <functional>

在这里插入图片描述

三、算法函数

STL将算法函数分成四组:
1)非修改式序列操作:对区间中的每个元素进行操作,这些操作不修改容器的内容。
2)修改式序列操作:对区间中的每个元素进行操作,这些操作可以容器的内容(可以修改值,也可以修改排列顺序)。
3)排序和相关操作:包括多个排序函数和其它各种函数,如集合操作。
4)通用数字运算:包括将区间的内容累积、计算两个容器的内部乘积、计算小计、计算相邻对象差的函数。通常,这些都是数组的操作特性,因此vector是最有可能使用这些操作的容器。

前三组在头文件#include <algorithm>中,第四组专用于数值数据,在#include <numeric>中。

在这里插入图片描述

  • eg:
    在这里插入图片描述
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using  namespace std;

template<typename T>
struct girl   {
	T   m_yz;         // 统计的颜值。
	int m_count;   // 符合条件的元素个数。

	girl(const T yz) : m_yz(yz), m_count(0) {}

	void operator()(const T& yz) {
		if (yz==m_yz) 	m_count++;
	}
};

int main()
{
	vector<int> vv = { 1,3,2,4,1,2,3,1,4,3 };   // 1-极漂亮;2-漂亮;3-普通;4-歪瓜裂枣
	
	//返回对象本身
	girl<int> g=for_each(vv.begin(), vv.end(), girl<int>(1));       // 按颜值统计超女人数。

	cout << "g.m_count=" << g.m_count << endl;
}

1.自己实现foreach算法

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using  namespace std;
/*
void zsshow(int const& no)    // 张三的个性化表白函数。
{
	cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
}
*/
template<typename T>
void zsshow(const T& no)    // 张三的个性化表白函数。
{
	cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
}
/*
class czs   // 张三的个性化表白仿函数。
{
public:
	void operator()(int const& no) {  
		cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
	}
};
*/
template<typename T>
class czs   // 张三的个性化表白仿函数。
{
public:
	void operator()(const T& no) {  
		cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
	}
};
/*
void foreach(const vector<int>::iterator first, const vector<int>::iterator last)
{
	for (auto it = first; it != last; it++)
		cout << "亲爱的" << *it << "号:我是一只傻傻鸟。\n";
}

void foreach(const vector<int>::iterator first, const vector<int>::iterator last, void(*pfnc)(int const&))
{
	for (auto it = first; it != last; it++)
		pfnc(*it);
}

void foreach(const vector<int>::iterator first, const vector<int>::iterator last, czs pfnc)
{
	for (auto it = first; it != last; it++)
		pfnc(*it);
}

*/
//这里模板的思想是传迭代器,若对象进行值传递或者引用传递,则只是支持某种类型的对象
template<typename T1, typename T2>
void foreach(const T1 first, const T1 last, T2 pfun)
{
	for (auto it = first; it != last; it++)
		pfun(*it);        // 以超女编号为实参调用类的operator()函数。
}

int main()
{
	vector<int> bh = { 5,8,2,6,9,3,1,7 };   // 存放超女编号的容器。
	//list<string> bh = { "05","08","02","06","09","03","01","07" };   // 存放超女编号的容器。

	// 写一个函数,在函数中遍历容器,向超女表白,表白的方法可自定义。
	foreach(bh.begin(), bh.end(), zsshow<int>);  // 第三个参数是模板函数。
	
	foreach(bh.begin(), bh.end(), czs<int>());       // 第三个参数是仿函数。
}

2.自己实现的findif算法

  • eg1:
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using  namespace std;

template<typename T>
bool zsshow(const T& no,const T & in_no)    // 张三的个性化表白函数。
{
	if (no != in_no) return false;
	cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
	return true;
}

template<typename T>
class czs   // 张三的个性化表白仿函数。
{
public:
	bool operator()(const T& no, const T& in_no) {
		if (no != in_no) return false;
		cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
		return true;
	}
};

template<typename T1, typename T2, typename T3>
T1 findif(const T1 first, const T1 last, T2 pfun,T3 in_no)
{
	for (auto it = first; it != last; it++)
		if (pfun(*it, in_no) ==true)  return it;        // 用迭代器调用函数对象。

	return last;
}

int main()
{
	vector<int> bh = { 5,8,2,6,9,33,1,7 };   // 存放超女编号的容器。
	//list<string> bh = { "05","08","02","06","09","03","01","07" };   // 存放超女编号的容器。

	auto it1=findif(bh.begin(), bh.end(), zsshow<int>,2);  // 第三个参数是模板函数。
	if (it1 == bh.end()) cout << "查找失败。\n";
	else cout << "查找成功:" << *it1 << endl;

	auto it2=findif(bh.begin(), bh.end(), czs<int>(),33);       // 第三个参数是仿函数。
	if (it2 == bh.end()) cout << "查找失败。\n";
	else cout << "查找成功:" << *it2 << endl;
}

  • eg2:更好的方式
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>  // STL算法函数头文件。
using  namespace std;

template<typename T>
bool zsshow(const T& no)    // 张三的个性化表白函数。
{
	if (no != 3) return false;
	cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
	return true;
}

template<typename T>
class czs   // 张三的个性化表白仿函数。
{
public:
	T m_no;     // 存放张三喜欢的超女编号。
	czs(const T& no) : m_no(no) {}  // 构造函数的参数是张三喜欢的超女编号。
	bool operator()(const T& no) {
		if (no != m_no) return false;
		cout << "亲爱的" << no << "号:我是一只傻傻鸟。\n";
		return true;
	}
};

template<typename T1, typename T2>
T1 findif(const T1 first, const T1 last, T2 pfun)
{
	for (auto it = first; it != last; it++)
		if (pfun(*it) ==true)  return it;        // 用迭代器调用函数对象。

	return last;
}

int main()
{
	vector<int> bh = { 5,8,2,6,9,33,1,7 };   // 存放超女编号的容器。
	//list<string> bh = { "05","08","02","06","09","03","01","07" };   // 存放超女编号的容器。

	auto it1=find_if(bh.begin(), bh.end(), zsshow<int>);  // 第三个参数是模板函数。
	if (it1 == bh.end()) cout << "查找失败。\n";
	else cout << "查找成功:" << *it1 << endl;

	auto it2=find_if(bh.begin(), bh.end(), czs<int>(8));       // 第三个参数是仿函数。
	if (it2 == bh.end()) cout << "查找失败。\n";
	else cout << "查找成功:" << *it2 << endl;
}

3.自己实现bsort算法

#include <iostream>
#include <vector>
#include <list>
#include <algorithm>   // STL算法函数。
#include <functional>   // STL仿函数。
using  namespace std;

template<typename T>
bool compasc(const T& left, const T& right)   {     // 普通函数,用于升序。
	return left < right;
}

template<typename T>
struct _less
{
	bool operator()(const T& left, const T& right) { // 仿函数,用于升序。
		return left < right;
	}
};

template<typename T>
bool compdesc(const T& left, const T& right) {     // 普通函数,用于降序。
	return left > right;
}

template<typename T>
class _greater
{
public:
	bool operator()(const T& left, const T& right) { // 仿函数,用于降序。
		return left > right;
	}
};

template<typename T, typename compare>
void bsort(const T first, const T last, compare comp)  // 冒泡排序。
{
	while(true)
	{
		bool bswap = false;        // 本轮遍历已交换过元素的标识,true-交换过,false-未交换过。
		for (auto it = first; ; )
		{
			auto left = it;                  // 左边的元素。
			it++;
			auto right = it;               // 右边的元素。
			if (right == last) break;  // 表示it1已经是最后一个元素了。

			//if (*left > *right)             // 如果左边的元素比右边大,交换它们的值。
			//if (*left < *right)             // 如果左边的元素比右边小,交换它们的值。
			// 排序规则:如果comp()返回true,left排在前面(升序),否则right排在前面(降序)。
			if (comp(*left, *right) == true)  continue;

			// 交换两个元素的值。
			auto tmp = *right;
			*right = *left;
			*left = tmp;
			bswap = true;        // 一轮遍历已交换过元素的标识。
		}

		if (bswap == false) break;  // 如果在for循环中不曾交换过元素,说明全部的元素已有序。
	}
}

int main()
{
	vector<int> bh = { 5,8,2,6,9,33,1,7 };   // 存放超女编号的容器。
	//list<string> bh = { "05","08","02","06","09","03","01","07" };   // 存放超女编号的容器。

	//bsort(bh.begin(), bh.end(),compasc<int>);        // 普通函数(升序)。
	//bsort(bh.begin(), bh.end(), compdesc<int>);     // 普通函数(降序)。

	//bsort(bh.begin(), bh.end(),_less<int>());             // 仿函数(升序)。
	//bsort(bh.begin(), bh.end(), _greater<int>());      // 仿函数(降序)。

	//bsort(bh.begin(), bh.end(), less<int>());             // STL提供的仿函数(升序)。
	//bsort(bh.begin(), bh.end(), greater<int>());       // STL提供的仿函数(降序)。

	//sort(bh.begin(), bh.end(),_less<int>());             // 仿函数(升序)。
	sort(bh.begin(), bh.end(), _greater<int>());      // 仿函数(降序)。

	for (auto val : bh)
		cout << val << " ";
	cout << endl;
}

  • ref:从0基础系统化学习C++,不可能学不会

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

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

相关文章

数据结构---用栈实现队列

用栈实现队列模拟入队模拟出队JAVA实现总结用栈来模拟一个队列&#xff0c;要求实现队列的两个基本操作&#xff1a;入队、出队。栈是先入后出&#xff0c;队列是先入先出 用两个栈来实现一个队列功能 让其中一个栈作为队列的入口&#xff0c;负责插入新元素&#xff1b;另一个…

ARM9和STM32什么关系?

已剪辑自: https://mp.weixin.qq.com/s/QHARY-D2SwFoQbFsJoCNlg 有小伙伴问&#xff1a;ARM9和STM32什么关系&#xff1f;如果时间倒退10年&#xff0c;ARM9、 s3c2410还算是比较流行的年代&#xff0c;但STM32这类“新时代”的ARM处理器也问世了。 ARM9是早期的ARM处理器&…

Java+MySQL基于ssm的打车管理系统的设计与实现

随着时代的发展,交通也变的越来越便利,但是很多时候人们出行的时候因为各种原因还是会进行打车,因为一些地区比较偏远或者处于特殊的时间段而用户又急需用车等情况导致没办法及时的打到车,这种情况下就急需一套基于互联网的打车系统出现了。 本打车管理系统采用JAVA语言来进行开…

Vivado2019+Modelsim仿真环境搭建

目录 一、安装准备 二、安装与配置 2.1 Vivado安装 2.2 modelsim安装 2.3 Vivado设置modelsim仿真环境 1&#xff09;仿真库生成设置 2&#xff09;modelsim添加仿真库&#xff08;逐个添加&#xff09; 3&#xff09;modelsim添加仿真库&#xff08;批量添加&#xff…

Spring 中 @Value 注解使用和源码分析

1、Value 注解使用 先配置本地 application.properties 如下&#xff1a; apple.nameabc代码如下&#xff1a; PropertySource("application.properties") public class Apple {Value("${apple.name}")public String name; }ComponentScan public class …

非零基础自学Golang 第9章 结构体 9.7 匿名结构体 9.8 小结 9.9 知识拓展

非零基础自学Golang 文章目录非零基础自学Golang第9章 结构体9.7 匿名结构体9.7.1 匿名结构体定义与初始化9.7.2 匿名结构体的应用9.8 小结9.9 知识拓展9.9.1 使用结构体解析XML文件第9章 结构体 9.7 匿名结构体 9.7.1 匿名结构体定义与初始化 匿名结构体&#xff0c;顾名思…

blender源代码编译运行

其实在blender官网上已经给出了编译步骤https://wiki.blender.org/wiki/Building_Blender/Windows&#xff0c;由于在源码编译的过程中还遇到了很多问题&#xff0c;特此记录一下。 文章目录前提准备代码下载1. blender源码下载2. lib下载编译前提准备 Visual Studio2019或者2…

Innodb存储引擎-执行流程分析和二阶段提交分析

文章目录执行流程分析基本流程WAL(Write-Ahead Log)write和fsync区别innodb_flush_logs_at_trx_commit & sync_binlog二阶段提交执行流程分析 基本流程 &#xff08;1&#xff09;连接,分析,优化,执行 客户端与MySQL Server建立连接&#xff0c;发送语句给MySQL Server&a…

2022.12.18 学习周报

文章目录摘要文献阅读1.题目2.摘要3.介绍4.RNNConventional Recurrent Neural Networks5.Deep Recurrent Neural Networks5.1 Deep Transition RNN5.2 Deep Output5.3 Stacked RNN6.实验6.1 训练6.2 结果与分析7.讨论深度学习GRU公式推导1.GRU前向传播2.GRU反向传播GRU代码实现…

关于数学中“函数(function)”的含义

目录 1. 问题 2. “function”是如何翻译成“函数”的&#xff1f; 3. “function”是谁引入数学中的&#xff0c;其意义何在&#xff1f; 3.1 “function”的词源 3.2 “function”引入数学中 3.3 “function”的含义 4. 常见的函数(Common Functions) 4.1 线性函数(L…

word页码如何设置为章节加页码,例如第一章第一页1-1、第二章章第一页2-1

由于用到word页码分章节页码的形式&#xff0c;从网上查了一下&#xff0c;质量真的很差&#xff0c;没有一篇文章讲清楚的&#xff0c;有的所答非所问&#xff0c;一怒之下&#xff0c;利用几个小时的时间解决问题并写下这篇文章&#xff0c;以供大家学习参考&#xff01;&…

【JSP】

文章目录简介Scriptlet脚本小程序JSP的指令标签include静态包含include动态包含不传参传参JSP的四大域对象四种属性范围验证属性范围的特点EL表达式操作字符串操作集合emptyJSTL条件动作标签if标签choose、when 和 otherwise 标签迭代标签foreach格式化动作标签formatNumber标签…

NProgress 进度条的使用方法

安装NProgress 进度条 npm install nprogress --save-dev 在vue项目中mian.js中或router.js或axios.js&#xff1a; import NProgress from nprogress import nprogress/nprogress.css 使用NProgress进度条 NProgress.start(); &#xff1a;进度条开始&#xff1b; NProgr…

GCD和LCM

目录 一 整除 定义 性质 二 GCD 1&#xff09;定义 2&#xff09;性质 3&#xff09;GCD编程 ①暴力法 ②欧几里得算法 ③更相减损术 ④Stein算法 三 LCM ①暴力法 ②最大公约数法 四 裴蜀定理 例题&#xff1a;裴蜀定理 一 整除 定义 a 能整除b,记为 a|b。其…

你还会想起这道题吗

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 原神是由米哈游自主研发的一款全新开放世界冒险游戏。游戏发生在一个被称作「提瓦特」的幻想世界&#xff0c;在这里&#xff0c;被神选中的人将被授予「神之眼」&#xff0c;导引元…

m基于神经网络的气候预测matlab仿真,气候数据采用的BoM气候数据,神经网络为matlab编程实现不使用工具箱函数

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 人工神经网络&#xff08;Artificial Neural Networks&#xff0c;简写为ANNs&#xff09;也简称为神经网络&#xff08;NNs&#xff09;或称作连接模型&#xff08;Connection Model&#xff09…

UICollectionView 实际使用

一. 使用UICollectionView制作书架 我想的书架是那种每一排都可以滑动的。暂时的想法是使用两个collectionView&#xff0c;第一个collectionView布置书架的每一排&#xff0c;第二个布置每一排内部的书。 布置外部的colletionView&#xff0c;这部分很简单&#xff0c;item的…

[ 数据结构 -- 手撕排序算法第五篇 ] 堆排序

文章目录前言一、常见的排序算法二、堆的概念及结构三、堆的实现3.1 堆的插入3.2 堆的删除四、堆排序4.1 向上调整建堆4.2 向下调整建堆4.3 建堆的时间复杂度4.4 堆排序五、堆排序的特性前言 手撕排序算法第五篇&#xff1a;堆排序&#xff01; 从本篇文章开始&#xff0c;我会…

Java+JSP超市管理系统(含源码+论文+答辩PPT等)

项目功能简介: 该项目采用的技术后台框架&#xff1a;Servlet、JSP、JDBC、UI界面&#xff1a;BootStrap、jQuery、数据库&#xff1a;MySQL 系统功能 该系统共包含两种角色&#xff1a;员工和管理员。系统的主要功能模块如下&#xff1a; 1.系统管理 系统登陆、系统退出、修改…

《Mysql是怎样运行的》补充

19 第19章 从猫爷被杀说起-事务简介 19.1 事务的起源 19.1.1 原子性&#xff08;Atomicity&#xff09; 19.1.2 隔离性&#xff08;Isolation&#xff09; 其它的状态转换不会影响到本次状态转换&#xff0c;这个规则被称之为 隔离性 19.1.3 一致性&#xff08;Consisten…