C++标准库常用的遍历和查找算法

文章目录

      • 1.常用遍历算法
        • 1.for_each
        • 2.transform
      • 2.常用查找算法
        • 1. find
        • 2. find_if
        • 3. adjacent_find
        • 4. binary_search
        • 5. count
        • 6. count_if

1.常用遍历算法

1.for_each

C++的std::for_each算法是标准库中的一个迭代器算法,它对容器或范围内的每个元素执行指定的操作。这个算法特别适用于你想要对容器内的每个元素应用同一个操作,但操作本身不需要积累结果(例如累加或查找最大值)的情形。std::for_each返回作用于每个元素的函数对象的副本。

基本语法如下:

template< class InputIt, class UnaryFunction>
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
  • InputIt first, InputIt last: 这是一个半开区间 [first, last),定义了要遍历的元素范围。
  • UnaryFunction f: 一个可调用的对象(如函数、lambda表达式或者函数对象),它接受一个参数(即容器中的元素类型)并对其进行操作。该对象会在区间内的每个元素上被调用。

示例:

#include <algorithm>
#include <iostream>
#include <vector>void print(int i) {std::cout << i << ' ';
}int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};// 使用std::for_each打印vector中的每个元素std::for_each(numbers.begin(), numbers.end(), print);return 0;
}

在这个例子中,print函数被传递给std::for_each,它会对numbers向量中的每个元素调用print函数,从而打印出向量中的所有数字。

自C++11起,还可以直接使用lambda表达式作为第三个参数,使得操作更加灵活:

std::for_each(numbers.begin(), numbers.end(), [](int i){ std::cout << i * 2 << ' '; });

这段代码会打印出向量中每个数字的两倍。

2.transform

C++的std::transform算法是标准库中的一个迭代器算法,用于将一个范围内或两个范围内的元素通过某个操作转换后存放到另一个范围。这个算法常用于对容器内容进行批量修改或计算转换后的结果。与std::for_each不同的是,std::transform通常涉及输入范围和输出范围,并且转换操作可能产生新的值。

基本语法如下:

// 单输入范围到单输出范围
template< class InputIt, class OutputIt, class UnaryOperation>
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, UnaryOperation unary_op);// 双输入范围到单输出范围
template< class InputIt1, class InputIt2, class OutputIt, class BinaryOperation>
OutputIt transform(InputIt1 first1, InputIt1 last1, InputIt2 first2, OutputIt d_first, BinaryOperation binary_op);
  • 对于单输入范围版本:

    • InputIt first1, InputIt last1: 定义了输入范围。
    • OutputIt d_first: 指向输出范围的开始位置。
    • UnaryOperation unary_op: 一个可调用对象,接受一个输入范围的元素作为参数,并返回转换后的结果。
  • 对于双输入范围版本:

    • InputIt1 first1, InputIt1 last1, InputIt2 first2: 分别定义了两个输入范围。
    • 其余参数同上,但BinaryOperation binary_op接受两个输入范围对应位置的元素作为参数,并返回一个转换后的结果。

示例:

单输入范围示例,将一个vector中的每个元素平方后存入另一个vector:

#include <algorithm>
#include <iostream>
#include <vector>int square(int x) {return x * x;
}int main() {std::vector<int> numbers = {1, 2, 3, 4, 5};std::vector<int> squared;// 保留足够空间以避免插入时重新分配squared.resize(numbers.size());// 使用std::transform进行转换std::transform(numbers.begin(), numbers.end(), squared.begin(), square);for(int num : squared) {std::cout << num << ' ';}return 0;
}

双输入范围示例,将两个vector对应元素相加后存入第三个vector:

#include <algorithm>
#include <iostream>
#include <vector>int main() {std::vector<int> vec1 = {1, 2, 3};std::vector<int> vec2 = {4, 5, 6};std::vector<int> result(vec1.size());// 使用std::transform进行转换,这里使用lambda表达式代替函数对象std::transform(vec1.begin(), vec1.end(), vec2.begin(), result.begin(), [](int a, int b){ return a + b; });for(int res : result) {std::cout << res << ' ';}return 0;
}

这些示例展示了如何使用std::transform进行简单的数值转换和组合操作。

2.常用查找算法

在C++标准库中,提供了多种查找算法来帮助处理容器或范围内的数据。以下是您提到的一些常用查找算法的简要说明:

1. find

std::find用于在一个范围内查找指定的值。如果找到该值,则返回指向该值的第一个匹配项的迭代器;如果没有找到,则返回表示范围末尾的迭代器。

基本用法:

template< class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T& value);

示例:

// 包含标准输入输出库、算法库和向量库
#include <iostream>
#include <algorithm>
#include <vector>// 使用标准命名空间,简化代码中标准库函数的调用
using namespace std;// 程序的主入口函数
int main(){// 初始化一个字符串变量namestring name = "Felipe";// 查找字符串name中字符'F'的位置auto in = find(name.begin(), name.end(),'F');// 输出找到的字符cout << *in << endl;// 初始化一个整数向量V,并赋初值vector<int>V = {1,2,3,5,6,7};// 在向量V中查找数值1的位置auto it = find(V.begin(), V.end(),1);// 判断是否找到数值1,如果找到则输出相应信息if(it != V.end()){cout << "find 1" << endl;}// 程序正常结束return 0;
}
2. find_if

std::find_if类似于find,但它不是直接查找特定值,而是使用提供的谓词(如函数、lambda表达式)来测试每个元素,直到找到第一个使谓词返回true的元素。如果找到这样的元素,则返回指向它的迭代器;否则,返回last

基本用法:

template< class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate pred);

示例:

// Filename: find_example.cpp
// Created by 86189 on 2024/7/7.
//
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;// 主函数,演示如何使用标准库函数find_if查找向量中第一个大于5的元素
int main() {// 初始化一个整数向量,包含1到6的几个数字,其中有重复vector<int> V = {1, 2, 3, 3, 4, 5, 6};// 使用find_if算法查找向量中第一个大于5的元素// find_if函数接受一个范围(向量的开始和结束迭代器)和一个谓词(用于判断条件的lambda表达式)// 这里lambda表达式返回值为true时意味着找到了满足条件的元素auto it = find_if(V.begin(), V.end(), [](const int &val) { return val > 5; });// 检查是否找到了满足条件的元素if (it != V.end()) {// 如果找到了,输出该元素的值cout << *it << endl;} else {// 如果没有找到,输出提示信息cout << "No element greater than 5 found." << endl;}return 0;
}
3. adjacent_find

std::adjacent_find用于查找序列中相邻重复的元素对。它返回一个指向序列中第一个重复元素的迭代器,如果序列中没有相邻的重复元素,则返回最后一个元素的下一个位置。

基本用法:

template< class InputIt >
InputIt adjacent_find( InputIt first, InputIt last );template< class InputIt, class BinaryPredicate >
InputIt adjacent_find( InputIt first, InputIt last, BinaryPredicate pred );

第二个版本接受一个比较谓词。

示例:

// 包含标准输入输出库和向量库
#include <iostream>
#include <vector>
#include <algorithm>
// 使用标准命名空间,简化代码中标准库函数的调用
using namespace std;// 程序入口函数
int main(){// 初始化一个整数向量v,包含一组数字vector<int>v = {0,1,3,4,5,5,7,7};// 使用adjacent_find函数查找向量v中相邻重复的元素// adjacent_find返回的是一个迭代器,指向第一个相邻重复元素的位置auto it = adjacent_find(v.begin(), v.end());// 如果找到相邻重复元素,输出该元素的值cout << *it << endl;// 使用lambda表达式作为谓词,查找向量v中相邻元素差值绝对值大于1的元素// 这里的lambda表达式接收两个int类型的引用,返回一个bool值// 它比较两个引用所指的元素的差值的绝对值是否大于1auto in = adjacent_find(v.begin(), v.end(),[](const int &val,const int &b){return (abs(b-val)>1);});// 如果找到满足条件的元素,输出该元素的值cout << *in << endl;// 程序正常结束return 0;
}
4. binary_search

std::binary_search在一个已排序的范围内查找特定值。如果找到了该值,则返回true;否则,返回false。这个算法假设范围是按升序排序的。

基本用法:

template< class ForwardIt, class T>
bool binary_search(ForwardIt first, ForwardIt last, const T& value);template< class ForwardIt, class T, class Compare>
bool binary_search(ForwardIt first, ForwardIt last, const T& value, Compare comp);

第二个版本接受一个比较函数。

示例:

#include <iostream>
#include <set>
#include <algorithm>
#include <vector>
using namespace std;int main() {// 使用set的查找,无需自定义比较函数,因为set本身就是有序的且默认升序set<int> s = {1, 2, 3, 4, 5, 6};if (binary_search(s.begin(), s.end(), 5)) {cout << "Found: " << 5 << endl; // 更正输出格式}// 对于vector,如果要使用非默认比较(例如降序),需要正确传递比较函数// 但是,注意binary_search要求容器是已排序的。先对vector排序vector<int> v = {1, 3, 6, 5, 8, 4, 6};sort(v.begin(), v.end(), [](const int &a, const int &b) { return a > b; }); // 先排序// 确保v是按所需顺序排序后,再使用binary_searchif (binary_search(v.begin(), v.end(), 5, [](const int &a, const int &b) { return a > b; })) {cout << "Found: " << 5 << endl; // 更正输出格式} else {cout << "Not found: " << 5 << endl; // 添加未找到时的输出}return 0;
}

注意:

binary_search算法要求其操作的范围必须是已排序的,不论是否提供了第四个比较函数参数。这是因为binary_search的工作原理基于二分查找算法,该算法的前提是输入数据是有序的。提供自定义的比较函数(即第四个参数)是为了适应不同的排序逻辑(如降序、自定义排序依据等),而不是为了处理无序数据。

如果输入范围是无序的,即使你提供了比较函数,binary_search的结果也是未定义的,可能会导致错误的查找结果。因此,在调用binary_search之前,你应该确保范围内的元素是按照你所指定的比较规则排序的。在上面的例子中,对vector<int> v应用了sort函数配合同样的比较函数进行了排序,之后才进行binary_search,这是正确的做法。

5. count

std::count计算范围内与给定值匹配的元素数量。

基本用法:

template< class InputIt, class T>
typename std::iterator_traits<InputIt>::difference_type count(InputIt first, InputIt last, const T& value);

示例:

//
// Created by 86189 on 2024/7/7.
//
#include <iostream>
#include <algorithm>
#include <vector>using namespace std;// 主函数,程序的入口点
int main(){// 初始化一个整数向量v,包含一组数字,用于后续的计数操作vector<int>v = {1,2,2,2,2,2,5,6,9,8};// 使用标准库函数count计算向量v中值为2的元素的数量,并输出结果cout << count(v.begin(), v.end(),2) << endl;return 0;
}
6. count_if

std::count_if类似于count,但它不是直接计数特定值,而是使用谓词来决定哪些元素应该被计数。

基本用法:

template< class InputIt, class UnaryPredicate>
typename std::iterator_traits<InputIt>::difference_type count_if(InputIt first, InputIt last, UnaryPredicate pred);

示例:

#include <iostream>
#include <algorithm>
#include <vector>using namespace std;// 主函数,程序的入口点
int main(){// 初始化一个整数向量,包含一组数字用于后续操作vector<int>v = {1,2,2,3,2,2,5,6,9,8};// 使用标准库函数count计算向量v中值为2的元素个数// 并将结果输出到标准输出流cout << count(v.begin(), v.end(),2) << endl;// 使用标准库函数count_if计算向量v中大于2的元素个数// 使用lambda表达式作为谓词,对每个元素进行判断cout << count_if(v.begin(), v.end(),[](const int &a){return a>2;});return 0;
}

这些算法是C++标准库 <algorithm> 头文件的一部分,为处理容器和数组提供了强大的工具。

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

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

相关文章

缺失行处理(R和python)

R(complete.cases) rm(listls()) # 创建一个包含缺失值的数据框 # df <- data.frame( # x c(1, 2, NA, 4), # y c(NA, 2, 3, 4), # z c(1, NA, 3, 3) # ) # # # 使用complete.cases函数筛选包含缺失值的数据行 # missing_rows <- !complete.cases(df) # # # …

Java的垃圾回收机制解说

Java 内存运行时区域中的程序计数器、虚拟机栈、本地方法栈随线程而生灭&#xff1b;栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的&#xff08;尽管在运行期会由 JIT 编译器进行一些优化&…

STM32+ESP8266连接阿里云

完整工程文件&#xff08;百度网盘免费下载&#xff0c;提取码&#xff1a;0625&#xff09;在文章末尾&#xff0c;需要请移步至文章末尾。 目录 宏定义配置 串口通信配置 消息解析及数据发送 ESP8266初始化 注意事项 完整工程文件 经过基础教程使用AT指令连接阿里云后…

使用vue3-treeselect问题

1.当vue3-treeselect是单选时&#xff0c;使用watch监听绑定value&#xff0c;无法监听到值清空 对照后将:value改为v-model&#xff0c;如图 2.使用vue3-treeselect全部清空按钮如何置空select的值&#xff0c;使用watch监听 多选&#xff1a;pageInfo.officeName(val) {// …

华为OD面试 - 简易Linux路径解析(Java JS Python C C++)

题目描述 某简易的 linux 目录系统 cd 命令(change directory)功能如下: cd:进入 home 目录 /home/usercd -:进入上一次停留的目录(连续两个以上 cd - 会在两个目录之间来回跳转,而不是回到更早之前的目录)cd <绝对路径>:以 / 开头的为绝对路径cd <相对路径…

【手写数据库内核组件】0201 哈希表hashtable的实战演练,多种非加密算法,hash桶的冲突处理,查找插入删除操作的代码实现

hash表原理与实战 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 hash表…

【TB作品】51单片机 Proteus仿真 MAX7219点阵驱动数码管驱动

1、8乘8点阵模块&#xff08;爱心&#xff09; 数码管测试程序与仿真 实验报告: MAX7219 数码管驱动测试 一、实验目的 通过对 MAX7219 芯片的编程与控制&#xff0c;了解如何使用单片机驱动数码管显示数字&#xff0c;并掌握 SPI 通信协议的基本应用。 二、实验器材 51…

多项式求和之九(给定程序中函数 fun 的功能是:求出以下分数序列的前 n 项之和,并通过函数值返回 main 函数。)

代码 #include <stdio.h> /********found********/ double fun(int n){double a2,b1,c,s0;while(n>0){n--; /********found********/ssa/b;ca;aab;bc;}return s; } void main(){int n;scanf("%d",&n);printf("%lf\n",fun(n)); }友情提示 1、…

期末上分站——计组(5)

简答题11-21 11、为了提高计算机系统的输入/输出能力&#xff0c;可以在总线的设计与实现中采用哪些方案&#xff1f; 答&#xff1a;1. 提高总线时钟频率 2. 增加数据总线的位数 3. 采用成组数据传送&#xff08;BURST传送&#xff09;方式 4. 采用多总线结构 5. 优化总线传输…

微深节能 煤码头自动化翻堆及取料集控系统 格雷母线

微深节能格雷母线高精度位移测量系统是一种先进的工业自动化位置检测解决方案&#xff0c;它被广泛应用于煤码头自动化翻堆及取料集控系统中&#xff0c;以实现对斗轮堆取料机等大型机械设备的精准定位和自动化控制。 系统原理简述&#xff1a; 格雷母线系统的工作原理基于电磁…

如何在Spring Boot中实现数据加密

如何在Spring Boot中实现数据加密 大家好&#xff0c;我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 一、数据加密的重要性与应用场景 在当今信息安全日益受到重视的背景下&…

软件工程需求之:业务需求与用户需求

在软件开发项目中&#xff0c;"业务需求"和"用户需求"是两个核心概念&#xff0c;它们分别从不同的角度描述了软件应该具备的功能和特性。理解这两个概念的区别对于成功地规划和开发软件至关重要。 业务需求 业务需求主要关注于软件项目如何帮助实现企业…

EOF 为 (End Of File) 的缩写 , 值通常为 -1

EOF是一个计算机术语&#xff0c;为 End Of File 的缩写 EOF 的值通常为 -1 EOF 的值通常为 -1&#xff0c;但它依系统有所不同。巨集 EOF会在编译原始码前展开实际值给预处理器。 与 feof 与 feof C语言中&#xff0c;当把数据以二进制形式存放到文件中时&#xff0c;就会有…

[AIGC] ClickHouse的表引擎介绍

ClickHouse是一种高性能的列式数据库管理系统&#xff0c;支持各种不同的表引擎。表引擎是数据库系统中的核心组件&#xff0c;它定义了数据的存储方式和访问方式。本文将介绍ClickHouse中常见的表引擎及其特点。 文章目录 一、MergeTree引擎二、ReplacingMergeTree引擎三、Sum…

阿里云ecs服务器,nginx多域名多项目部署教程,含本地部署教程

nginx多域名部署项目 本地部署线上部署 一、本地部署 第一步&#xff1a; winr 输入drivers 打开hosts文件&#xff0c;编辑 加行 127.0.0.1 自定义域名 … 第二步&#xff1a; 下载 nginx 安装好以后 打开ngin安装目录&#xff0c;选择nginx.conf 打开 #user Administ…

前端面试题10(js多位数组变一维数组)

1. 使用concat()和递归 function flatten(arr) {return arr.reduce((acc, val) > Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), []); }let multiDimArray [[1, 2, [3]], 4]; let flatArray flatten(multiDimArray); console.log(flatArray); // 输…

C++ STL IO流介绍

目录 一:IO流的继承关系: 二:输入输出功能 1. 基本用法 2. 格式化输入 3.非格式化输入 4. 格式化输出 三:流 1. 字符流 2. 向字符流中写入数据 3. 从字符流中读出数据 4. 清空字符流 5.完整的例子 四:文件流 一:IO流的继承关系: 类含义basic_streambuf 读取…

Python的`queue`模块

队列&#xff08;Queue&#xff09; 在Python的queue模块中&#xff0c;Queue类是一个线程安全的队列实现&#xff0c;用于在多线程编程中安全地交换信息。它遵循先入先出&#xff08;FIFO&#xff09;的原则。Queue类提供了几种主要的方法&#xff1a; put(item): 将一个项目…

动态规划|剑指 Offer II 093. 最长斐波那契数列

如果数组 arr 中存在三个下标 i、j、k 满足 arr[i]>arr[j]>arr[k] 且 arr[k]arr[j]arr[i]&#xff0c;则 arr[k]、arr[j] 和 arr[i] 三个元素组成一个斐波那契式子序列。由于数组 arr 严格递增&#xff0c;因此 arr[i]>arr[j]>arr[k] 等价于 i>j>k。 把这道题…

OPPO手机终极保活方案

Push应用解决CPU休眠应用锁OPPO的电源设置和应用省电设置 要保证OPPO手机的性能足够, 比如内存8G, 否则可能会因为性能不足而被杀死 为了保证长期流畅运行, 应该设置手机定时重启, 比如通过系统设置每天重启, 部分手机不重启会慢慢变卡 需要大量测试去验证方案的普遍性, 就算…