当前位置: 首页 > news >正文

Day 30 C++ STL 常用算法(上)

文章目录

  • 算法概述
  • 常用遍历算法
      • for_each——实现遍历容器
          • 函数原型
          • 示例
      • transform——搬运容器到另一个容器中
          • 函数原型
          • 注意
          • 示例
  • 常用查找算法
      • find——查找指定元素
          • 函数原型
          • 示例
      • find_if—— 查找符合条件的元素
          • 函数原型
          • 示例
      • adjacent_find——查找相邻重复元素
          • 函数原型
          • 示例
      • binary_search——查找指定元素是否存在
          • 函数原型
          • 示例
      • count——统计元素个数
          • 函数原型
          • 示例
      • count_if——统计符合条件的元素个数
          • 函数原型
          • 示例

算法概述

  • 算法主要是由头文件<algorithm> <functional> <numeric>组成。
  • <algorithm>头文件是STL中最大的头文件之一,它提供了一系列的算法操作,包括比较、交换、查找、遍历、复制、修改等等。

排序算法:sort()、stable_sort()、partial_sort()等。
查找算法:find()、find_if()、binary_search()等。
数值算法:accumulate()、inner_product()、adjacent_difference()等。
复制和移动算法:copy()、move()、copy_if()等。
修改算法:transform()、replace()、fill()、generate()等。
遍历算法:for_each()、count()、count_if()等。
合并和重排算法:merge()、reverse()、rotate()等。

  • <numeric>头文件相对较小,主要包括一些简单的数学运算函数。这些函数通常应用于序列上,例如数组或容器。

累加算法:accumulate(),实现对序列中元素进行累加求和。
内积算法:inner_product(),计算两个序列的内积。
部分和算法:partial_sum(),计算序列的部分和。
邻接差算法:adjacent_difference(),计算序列每对相邻元素的差值。
乘积算法:reduce(),计算序列中元素的乘积。

  • <functional>头文件定义了一些模板类,用于声明函数对象。函数对象是一种类对象,可以像函数一样调用。

算术类:plus、minus、multiplies、divides等。
比较类:equal_to、greater、less、not_equal_to等。
逻辑类:logical_and、logical_or、logical_not等。
一元函数适配器:negate、bind1st、bind2nd等。
二元函数适配器:not1、not2、compose1、compose2等。

这些函数对象类可以与算法和其他STL组件一起使用,以提供更灵活和可定制的功能。

常用遍历算法

for_each——实现遍历容器

实际开发中是最常用的遍历算法

函数原型
  • for_each(iterator beg, iterator end, _func);

参数说明

  • beg:要遍历的容器的起始迭代器。
  • end:要遍历的容器的结束迭代器,指向容器中最后一个元素的下一个位置。
  • _func:要在每个元素上执行的函数或函数对象。该函数或函数对象对传入的元素进行处理。
示例
#include <iostream>
#include <vector>
#include <algorithm>void printNum(int num) {std::cout << num << " ";
}int main() {std::vector<int> nums = {1, 2, 3, 4, 5};// 使用 for_each() 遍历容器中的元素,并调用 printNum() 函数输出每个元素std::for_each(nums.begin(), nums.end(), printNum);// 输出结果: 1 2 3 4 5return 0;
}

transform——搬运容器到另一个容器中

transform() 函数会遍历源容器中的元素,并将每个元素传递给 _func 进行转换操作,然后将转换结果存储到目标容器中。

函数原型
  • transform(iterator beg1, iterator end1, iterator beg2, _func);

//beg1 源容器开始迭代器

//end1 源容器结束迭代器

//beg2 目标容器开始迭代器

//_func 函数或者函数对象

注意

搬运的目标容器必须要提前开辟空间,否则无法正常搬运

示例
#include <iostream>
#include <vector>
#include <algorithm>int square(int x) {return x * x;
}int main() {std::vector<int> nums = {1, 2, 3, 4, 5};std::vector<int> squares(nums.size()); // 目标容器// 使用 transform() 算法将 nums 中的每个元素平方,并将结果存储到 squares 容器中std::transform(nums.begin(), nums.end(), squares.begin(), square);// 输出转换后的结果for (int num : squares) {std::cout << num << " ";}// 输出结果: 1 4 9 16 25return 0;
}

常用查找算法

算法简介:

  • find //查找元素
  • find_if //按条件查找元素
  • adjacent_find //查找相邻重复元素
  • binary_search //二分查找法
  • count //统计元素个数
  • count_if //按条件统计元素个数

find——查找指定元素

按值查找元素,找到返回指定元素的迭代器,找不到返回结束迭代器end()

函数原型
  • find(iterator beg, iterator end, value);

    // beg 开始迭代器

    // end 结束迭代器

    // value 查找的元素

示例
#include <iostream>
#include <vector>
#include <algorithm>int main() {std::vector<int> nums = {1, 2, 3, 4, 5};// 使用 find() 算法在 nums 容器中查找元素值为 3 的元素auto it = std::find(nums.begin(), nums.end(), 3);// 判断是否找到了匹配的元素if (it == nums.end() && *it == num) {std::cout << "未找到元素值为 3 的元素" << std::endl;} else {std::cout << "找到了元素值为 3 的元素" << std::endl;}return 0;
}

在上面的例子中,我们定义了一个 nums 容器,并使用 find() 算法在容器中查找值为 3 的元素。

如果找到了匹配的元素,find() 函数将返回指向该元素的迭代器,并将其赋值给变量 it。我们可以通过判断 it 是否等于容器的结束迭代器 nums.end() 来确定是否找到了匹配的元素。

最后,根据判断结果输出相应的信息。

如果在上述示例中,nums 容器中存在值为 3 的元素,那么输出将是 “找到了元素值为 3 的元素”;如果不存在值为 3 的元素,输出将是 “未找到元素值为 3 的元素”。


find_if—— 查找符合条件的元素

函数原型
  • find_if(iterator beg, iterator end, _Pred);

    // 按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

    // beg 开始迭代器

    // end 结束迭代器

    // _Pred 函数或者谓词(返回bool类型的仿函数)(用于确定元素是否满足条件的谓词函数对象。)

示例
#include <algorithm>
#include <vector>
#include <string>
//内置数据类型
class GreaterFive
{
public:bool operator()(int val){return val > 5;}
};void test01() {vector<int> v;for (int i = 0; i < 10; i++) {v.push_back(i + 1);}vector<int>::iterator it = find_if(v.begin(), v.end(), GreaterFive());if (it == v.end()) {cout << "没有找到!" << endl;}else {cout << "找到大于5的数字:" << *it << endl;}
}//自定义数据类型
class Person {
public:Person(string name, int age){this->m_Name = name;this->m_Age = age;}
public:string m_Name;int m_Age;
};class Greater20
{
public:bool operator()(Person &p){return p.m_Age > 20;}};void test02() {vector<Person> v;//创建数据Person p1("aaa", 10);Person p2("bbb", 20);Person p3("ccc", 30);Person p4("ddd", 40);v.push_back(p1);v.push_back(p2);v.push_back(p3);v.push_back(p4);vector<Person>::iterator it = find_if(v.begin(), v.end(), Greater20());if (it == v.end()){cout << "没有找到!" << endl;}else{cout << "找到姓名:" << it->m_Name << " 年龄: " << it->m_Age << endl;}
}int main() {//test01();test02();system("pause");return 0;
}

adjacent_find——查找相邻重复元素

函数原型
  • adjacent_find(iterator beg, iterator end);

    // 查找相邻重复元素,返回相邻元素的第一个位置的迭代器

    // 找不到则返回最后一个位置的迭代器

    // beg 开始迭代器

    // end 结束迭代器

注意

面试题中如果出现查找相邻重复元素,记得用STL中的adjacent_find算法

示例
#include <algorithm>
#include <vector>void test01()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(5);v.push_back(2);v.push_back(4);v.push_back(4);v.push_back(3);//查找相邻重复元素vector<int>::iterator it = adjacent_find(v.begin(), v.end());if (it == v.end()) {cout << "找不到!" << endl;}else {cout << "找到相邻重复元素为:" << *it << endl;}
}

binary_search——查找指定元素是否存在

函数原型
  • bool binary_search(iterator beg, iterator end, value);

    // 查找指定的元素,查到 返回true 否则false

    // 注意: 在无序序列中不可用

    // beg 开始迭代器

    // end 结束迭代器

    // value 查找的元素

配合二分查找法查找效率很高,值得注意的是查找的容器中元素必须的有序序列

示例
#include <algorithm>
#include <vector>void test01()
{vector<int>v;for (int i = 0; i < 10; i++){v.push_back(i);}//二分查找bool ret = binary_search(v.begin(), v.end(),2);if (ret){cout << "找到了" << endl;}else{cout << "未找到" << endl;}
}int main() {test01();system("pause");return 0;
}

count——统计元素个数

函数原型
  • count(iterator beg, iterator end, value);

    // 统计元素出现次数

    // beg 开始迭代器

    // end 结束迭代器

    // value 统计的元素

注意: 统计自定义数据类型时候,需要配合重载 operator==

示例
#include <iostream>
#include <algorithm>
#include <vector>struct Person {std::string name;int age;// 重载 operator== 运算符bool operator==(const Person& other) const {return name == other.name && age == other.age;}
};int main() {std::vector<Person> people = {{"Alice", 25},{"Bob", 30},{"Alice", 25},{"Charlie", 35},{"Alice", 25}};Person target = {"Alice", 25};int count = std::count(people.begin(), people.end(), target);std::cout << "The person " << target.name << " with age " << target.age << " appears " << count << " times." << std::endl;return 0;
}

在这个例子中,我们定义了一个结构体Person,其中包含姓名(name)和年龄(age)两个成员变量。然后,我们重载了operator==运算符,以便能够比较两个Person对象是否相等。

在main函数中,我们创建了一个people向量,其中包含了几个Person对象。我们想要统计具有姓名为"Alice"且年龄为25的人出现的次数。使用std::count函数,我们传入了people的迭代器范围以及目标对象target,并得到了出现次数。最后,输出结果即为该人物出现的次数。

count_if——统计符合条件的元素个数

函数原型
  • count_if(iterator beg, iterator end, _Pred);

    // 按条件统计元素出现次数

    // beg 开始迭代器

    // end 结束迭代器

    // _Pred 谓词

示例
#include <iostream>
#include <algorithm>
#include <vector>int main() {std::vector<int> numbers = {5, 15, 8, 12, 20, 30, 7, 10};// 统计大于10的元素个数int count = std::count_if(numbers.begin(), numbers.end(), [](int num) {return num > 10;});std::cout << "The number of elements greater than 10: " << count << std::endl;return 0;
}

输出
The number of elements greater than 10: 5


在上面的代码中,我们定义了一个整数向量numbers,其中包含了一些整数。然后,我们使用std::count_if函数来统计大于10的元素个数。为了指定统计条件,我们传递了一个匿名的Lambda表达式作为谓词参数。Lambda表达式的函数体是return num > 10;,它表示当传入的num大于10时返回true,否则返回false。

总结:按值统计用count,按条件统计用count_if

http://www.lryc.cn/news/123589.html

相关文章:

  • MES系统在机器人行业生产管理种的运用
  • Spark(39):Streaming DataFrame 和 Streaming DataSet 输出
  • 【云原生】Docker 详解(一):从虚拟机到容器
  • 代码随想录第48天 | 198. 打家劫舍、213. 打家劫舍II、337. 打家劫舍III
  • 【LeetCode】按摩师
  • 国际腾讯云账号云核算概述!!
  • .NET 6.0 重启 IIS 进程池
  • 一位心理学教师对ChatGPT的看法,提到了正确地使用它的几个要点
  • 认识Node.js及三个模块
  • 49 | 公司销售数据分析
  • Android 项目导入高德SDK初次上手
  • 生成树协议用来解决网络风暴的问题?(第三十二课)
  • git分支操作
  • 【基础学习笔记 enum】TypeScript 中的 enum 枚举类型介绍
  • SpringBoot中间件使用之EventBus、Metric、CommandLineRunner
  • ffmpeg命令行是如何打开vf_scale滤镜的
  • 【Vue3】自动引入插件-`unplugin-auto-import`
  • 每日温度(力扣)单调栈 JAVA
  • 博客项目(Spring Boot)
  • 修改Jenkins存储目录
  • 数据结构【第4章】——栈与队列
  • android webview 显示灰度网页
  • Linux操作系统的基础使用技能的训练大纲(超级详细版本适合于初学者)
  • 【变形金刚02】注意机制以及BERT 和 GPT
  • 一个脚本 专治杂乱
  • springboot 基础
  • web集群学习:基于nginx的反向代理和负载均衡
  • 编程小窍门: 一个简单的go mutex的小例子
  • 【工作记录】mysql中实现分组统计的三种方式
  • 马来西亚的区块链和NFT市场调研