【STL十八】算法——不修改序列的操作(for_each、count、find、equal、search)

2023-05-16

【STL十八】算法——不修改序列的操作(for_each、count、find、equal、search)

  • 一、简介
  • 二、头文件
  • 三、分类
  • 四、不修改序列的操作
    • 1、for_each
    • 2、count、count_if
    • 3、find、find_if
    • 4、euqal
    • 5、search

  • 前言:在前面我们讲解容器和函数对象时,都刻意的回避了算法,在此,我们单独分一篇文章,来讲解下stl提供的算法。

一、简介

STL算法部分主要是由三个头文件承担: algorithm、numeric、functional

  • algorithm:意思是算法,只要想使用STL库中的算法函数就得包含该头文件。
  • numeric:包含了一系列用于计算数值序列的算法,其具有一定的灵活性,也能够适用于部分非数值序列的计算
  • functional:定义了一些模板,可以用来声明函数对象。

本文,我们讲解下algorithm提供的算法。

二、头文件

#include <algorithm>

三、分类

根据网站https://www.apiref.com/cpp-zh/cpp/header.html显示,头文件<algorithm>提供的算法如下图。

  • 常用的分类
    • 不修改序列的操作
    • 修改序列的操作
    • 排序操作
    • 集合操作

在这里插入图片描述

四、不修改序列的操作

项目Value
for_each()在范围的每个元素上应用提供的函数。
count()返回范围内值的出现次数。
count_if()返回满足条件的范围的值的出现次数。
find()查找元素的第一个匹配项。
find_if()查找满足条件的元素的第一个匹配项。
equal()测试两组元素是否相等。 两组的大小不必相等。
search()用于在序列 A 中查找序列 B 第一次出现的位置。

1、for_each

for_each在容器中的使用

  • 普通函数
  • 仿函数(函数对象)
  • lambda表达式
// C++98
template <class InputIterator, class Function>
Function for_each (InputIterator first, InputIterator last, Function fn);

参数 (Parameters)
first - 将迭代器输入到初始位置。
last - 最终位置的最终迭代器。
fn - 接受范围内元素作为参数的一元函数。


返回值
返回函数fn 。

  • demo
// for_each example
#include <iostream> 
#include <algorithm>  
#include <vector>  

// 普通函数
void myfunction(int i) { 
	std::cout << ' ' << i;
}

// 函数对象
class FunctionObject {  
public:
	void operator() (int i) 
	{ 
		std::cout << ' ' << i; 
	}
} ;

// lamdba表达式
auto f = [](int i)
{
	std::cout << ' ' << i;
};

int main() {
	std::vector<int> myvector = {1,3,5};

	//给 for_each 传递一个函数
	std::cout << "myvector contains:";
	for_each(myvector.begin(), myvector.end(), myfunction);  
	std::cout << '\n';

	//给 for_each 传递一个函数对象
	std::cout << "myvector contains:";
	FunctionObject fo;
	for_each(myvector.begin(), myvector.end(), fo);  
	std::cout << '\n';

	// 给 for_each 传递一个lamdba
	std::cout << "myvector contains:";
	for_each(myvector.begin(), myvector.end(), f); 
	std::cout << '\n';

	return 0;
}

输出

myvector contains: 1 3 5
myvector contains: 1 3 5
myvector contains: 1 3 5

2、count、count_if

  • count
//C++98
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count (InputIterator first, InputIterator last, const T& val);

参数 (Parameters)
first - 将迭代器输入到搜索序列的初始位置。
last - 将迭代器输入到搜索序列的最终位置。
val - 要在范围内搜索的值。


返回值
返回第一个到最后一个范围内的元素数。

  • count_if
// C++98
template <class InputIterator, class Predicate>
typename iterator_traits<InputIterator>::difference_type
count_if (InputIterator first, InputIterator last, UnaryPredicate pred);

参数 (Parameters)
first - 将迭代器输入到搜索序列的初始位置。
last - 将迭代器输入到搜索序列的最终位置。
pred - 一元谓词,它接受一个参数并返回bool。


返回值
返回pred返回true的范围内的元素数。

  • demo
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool mygreater(int n) {
	return (n > 3);
}

int main(void) {
	vector<int> v = { 1, 3, 3, 3, 3 , 4, 5};

	// count
	int cnt;
	cnt = count(v.begin(), v.end(), 3);
	cout << "Number 3 occurs " << cnt << " times." << endl;

	// count_if
	int cnt2;
	cnt2 = count_if(v.begin(), v.end(), mygreater);
	cout << "There are " << cnt2 << " numbers are greater that 3." << endl;
	
	return 0;
}

输出

Number 3 occurs 4 times.
There are 2 numbers are greater that 3.

3、find、find_if

  • 模板及参数请参考cout、count_if
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

bool unary_pre(int n) {
    return ((n % 2) == 0);
}

int main(void) {
    int val = 5;
    vector<int> v = { 1, 2, 3, 4, 5 };
    auto result = find(v.begin(), v.end(), val);
    if (result != end(v))
        cout << "Vector contains element " << val << endl;
    
    auto it = find_if(v.begin(), v.end(), unary_pre);
    if (it != end(v))
        cout << "First even number is " << *it << endl;

    return 0;
}

输出

Vector contains element 5
First even number is 2

4、euqal

  • 3 个输入迭代器参数,前两个参数是第一个序列的开始和结束迭代器,第三个参数是第二个序列的开始迭代器。
  • 如果第二个序列中包含的元素少于第一个序列,结果是未定义的。 第2个长度要大于第1个的。
  • 4 个参数:第一个序列的开始和结束迭代器,第二个序列的开始和结束迭代器,如果两个序列的长度不同,那么结果总是为 false。本节会演示这两个版本,但推荐使用接受 4 个参数的版本,因为它不会产生未定义的行为。
  • demo
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void) {
    vector<int> v1 = { 1, 2, 3, 4, 5 };
    vector<int> v2 = { 2, 3, 4, 5, 6};

    bool result;
    result = equal(v1.begin(), v1.end(), v2.begin());
    if (result == false)
        cout << "Vector range is not equal." << endl;

    result = equal(v1.begin()+1, v1.end(), v2.begin());
    if (result == true)
        cout << "Vector range is equal." << endl;

    result = equal(v1.begin() + 1, v1.end(), v2.begin(),v2.end());
    if (result == false)
        cout << "Vector range is not equal." << endl;

    result = equal(v1.begin() + 1, v1.end(), v2.begin(), v2.end()-1);
    if (result == true)
        cout << "Vector range is equal." << endl;
    return 0;
}

输出

Vector range is not equal.
Vector range is equal.
Vector range is not equal.
Vector range is equal.

  • 第1条语句中,两个序列的第一个元素直接就不匹配,所以结果为 false。
  • 第 2条语句的输出为 true,因为 v1 的第二个元素到最后一个元素都从 v2 的第一个元素开始匹配。第二个序列的元素个数比第一个序列的元素个数多 1,但 第一个序列的元素个数决定了比较多少个对应的元素。
  • 第3条语句的输出为 false,因为序列是不同的。这条语句不同于前面的 equal() 调用,因为指定了第二个序列的结束迭代器。
  • 第4 条语句会从 v1 的第二个元素开始,与 v2 从第一个元素开始比较相同个数的元素,所以输出为 true。

5、search

  • find_end() 函数用于在序列 A 中查找序列 B 最后一次出现的位置。那么,如果想知道序列 B 在序列 A 中第一次出现的位置,该如何实现呢?可以借助 search() 函数。

  • search() 函数其功能恰好和 find_end() 函数相反,用于在序列 A 中查找序列 B 第一次出现的位置

#include <iostream> 
#include <vector> 
#include <algorithm> 
using namespace std;
int main()
{
    int i, j;

    // Declaring the sequence to be searched into 
    vector<int> v1 = { 1, 2, 3, 4, 5, 6, 7 };

    // Declaring the subsequence to be searched for 
    vector<int> v2 = { 3, 4, 5 };

    // Declaring an iterator for storing the returning pointer 
    vector<int>::iterator i1;

    // Using std::search and storing the result in 
    // iterator i1 
    i1 = std::search(v1.begin(), v1.end(), v2.begin(), v2.end());

    // checking if iterator i1 contains end pointer of v1 or not 
    if (i1 != v1.end()) {
        cout << "vector2 is present at index " << (i1 - v1.begin()) << endl;
    }
    else {
        cout << "vector2 is not present in vector1" << endl;
    }


    // Declaring the subsequence to be searched for 
    vector<int> v3 = { 3, 4, 6 };
    vector<int>::iterator i2;
    i2 = std::search(v1.begin(), v1.end(), v3.begin(), v3.end());
    if (i2 != v1.end()) {
        cout << "vector3 is present at index " << (i2 - v1.begin()) << endl;
    }
    else {
        cout << "vector3 is not present in vector1" << endl;
    }

    return 0;
}

输出

vector2 is present at index 2
vector3 is not present in vector1

  • 也可以使用函数对象;(二元谓词)
#include <iostream> 
#include <vector> 
#include <algorithm> 
using namespace std;

// Defining the BinaryPredicate function 
bool pred(int i, int j)
{
    cout << i << ";" << j<< endl;
    if (i > j) {
        return 1;
        
    }
    else {
        return 0;
    }
}

int main()
{
    int i, j;

    // Declaring the sequence to be searched into 
    vector<int> v1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

    // Declaring the subsequence to be compared to based 
    // on predicate 
    vector<int> v2 = { 2, 3, 6 };

    // Declaring an iterator for storing the returning pointer 
    vector<int>::iterator i1;

    // Using std::search and storing the result in 
    // iterator i1 based on predicate pred 
    i1 = std::search(v1.begin(), v1.end(), v2.begin(), v2.end(), pred);

    cout << *i1 <<endl;

    // checking if iterator i1 contains end pointer of v1 or not 
    if (i1 != v1.end()) {
        cout << "vector1 elements are greater than vector2 starting "
            << "from position " << (i1 - v1.begin());
    }
    else {
        cout << "vector1 elements are not greater than vector2 "
            << "elements consecutively.";
    }

    return 0;
}

输出

1;2
2;2
3;2
4;3
5;6
4;2
5;3
6;6
5;2
6;3
7;6
5
vector1 elements are greater than vector2 starting from position 4

说明

  • vector,v1中的{5,6,7},第一次出现比v2中的{ 2, 3, 6 }大

参考
1、C++ STL 容器库 中文文档
2、STL教程:C++ STL快速入门
3、https://www.apiref.com/cpp-zh/cpp/header.html
4、https://en.cppreference.com/w/cpp/header
5、WIKI教程_C ++标准库_C++ Library - <algorithm>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STL十八】算法——不修改序列的操作(for_each、count、find、equal、search) 的相关文章

  • 使用 pybind11 修改 std::array 的默认值

    我的目标是修改在中声明的数组C struct并赋予默认值 我读过了this https pybind11 readthedocs io en stable advanced cast stl html making opaque types
  • 如何在 C++ 中对四元结构进行有效排序?

    我有一个包含 x y z 和 w 成员的结构 如何高效排序 在 C 中首先按 x 然后按 y 按 z 最后按 w 如果你想实现字典排序 那么最简单的方法是使用std tie实现小于或大于比较运算符或函子 然后使用std sort http
  • Windows 相当于 Unix find 命令,用于搜索多种文件类型

    虽然在 Windows 中安装了 cygwin 可以提供大部分 unix 命令 但我仍然想知道如何使用 Windows find 命令在一个命令中搜索多个文件类型 ie find name cpp o name h o name java
  • 处理右值时的 insert 与 emplace

    std string myString std unordered set
  • 为什么我不能执行 std::map.begin() + 1?

    我有一个std map 我想从第二个条目开始迭代 我可以解决这个问题 但我对为什么 明显 语法无法编译感到困惑 该错误消息没有帮助 因为它指的是std string 我在这里没有使用它 这是一些代码 Suppose I have some
  • 使用 std::ios_base::binary 有什么意义?

    我在 Window 下读取 Linux 文件时遇到问题 以下是问题讨论 在 Windows 下对 Unix 下创建的文件使用 fstream seekg https stackoverflow com questions 26973274
  • 如何将一对 std::pair 插入另一个 std::pair 中?

    我将字符串映射到一对对 如下所示 std map
  • 如何以最佳方式计算 python 列表中的元素数量

    这几乎是同一个问题here https stackoverflow com questions 3710976 counting unique elements in a list 除了我要询问排序结果的最有效解决方案 我有一个列表 大约
  • 如何在给定位置的情况下获取列表中的某个元素?

    所以我有一个清单 list myList myList push back Object myObject 我不确定 但我确信这将是数组中的 第 0 个元素 我可以使用任何函数来返回 myObject 吗 Object copy myLis
  • 使用 STL 算法与容器(char * 除外)进行 C++ 二进制文件 I/O

    我正在尝试使用 STL 复制算法对二进制文件 I O 进行简单测试 以将数据复制到容器和二进制文件中 从容器和二进制文件中复制数据 见下文 1 include
  • Jquery $.each 选择器

    我想知道什么 each 在 jquery 中代表 它在选择什么 原型中有等效的吗 each 没有选择任何东西 它只是一个迭代集合的实用程序 当你这样做时 someSelector each function do something jQu
  • jquery 在单击的实例之后查找下一个图像

    我正在尝试建立一个图像库 您可以在其中单击拇指 然后可以使用下一个和上一个按钮 我的问题是用户最初可以单击我需要检测的任何图像以及下一个或上一个图像的锻炼 并将显示 src 替换为下一个图像的 src 我只是想让下一个按钮首先工作 因为前一
  • 跨 dll 边界的内存分配和释放

    我知道在一个 dll 中进行内存分配然后在另一个 dll 中释放内存可能会导致各种问题 尤其是与 CRT 相关的问题 当涉及到导出 STL 容器时 此类问题尤其成问题 我们之前遇到过此类问题 在编写与我们的库链接的自定义 Adob e 插件
  • C++ std::list:迭代时擦除/删除元素[重复]

    这个问题在这里已经有答案了 可能的重复 您可以在迭代 std list 时从其中删除元素吗 https stackoverflow com questions 596162 can you remove elements from a st
  • 此 C++ 模板中的迭代器类型应该是什么?

    前一段时间在处理一些图形代码时 我使用整数作为底层坐标持有者编写了 Rect 和 Region 类 并且效果很好 Region 被实现为 STL 列表的简单类扩展 并且仅包含 矩形列表 现在我还需要使用双精度作为底层坐标持有者的相同类型的类
  • 使用mysql在一个查询中选择多个表中的子项总数

    我整个下午都在尝试处理一个查询 或两个或三个 以获得三个表的所有子表的计数 看看我的设计 用户表 id user name 1 foo 2 bar 赢表 id won user 1 1 2 1 3 2 绘制表格 id draw user 1
  • 将向量转换为整数

    我正在寻找用于将整数向量转换为普通整数的预定义函数 但我没有找到 vector
  • 计算每个唯一值出现的次数

    假设我有 v rep c 1 2 2 2 25 现在 我想计算每个唯一值出现的次数 unique v 返回唯一值是什么 但不返回它们的数量 gt unique v 1 1 2 我想要一些能给我的东西 length v v 1 1 25 le
  • DotNET 应用程序中的 GDI 句柄

    我的纯 DotNET 库作为非托管桌面应用程序中的插件运行 我收到了稳定的 虽然低 崩溃报告流 这些报告似乎表明 GDI 句柄存在问题 错误消息中的字体等 恢复为系统字体 各种控件的显示崩溃 不久后发生大规模崩溃 我的窗体几乎没有控件 但我
  • 限制 jQuery id 字符串吗?

    简而言之 我的问题是字符串在 jQuery 中作为可搜索 id 或可搜索内容有什么限制 更新 我得到了 ID 部分 但不是为什么我什至无法使用该字符串搜索 html 内容 对于任何愿意告诉我一个正则表达式来将模式从 MM dd yy HH

随机推荐