C++ STL算法系列2---find ,find_first_of , find_if , adjacent_find的使用

简介: 一.find运算 假设有一个int型的vector对象,名为vec,我们想知道其中是否包含某个特定值。 解决这个问题最简单的方法时使用标准库提供的find运算: 1 // value we'll look for 2 int search_value = 42; 3 4 /...

一.find运算

假设有一个int型的vector对象,名为vec,我们想知道其中是否包含某个特定值

解决这个问题最简单的方法时使用标准库提供的find运算:

 1 // value we'll look for
 2 int search_value = 42;
 3 
 4 //call find to see if that value is present
 5 vector<int>::const_iterator result = find(vec.begin() , vec.end() , search_value);
 6 
 7 //report the result
 8 cout<<"The value "<<search_value
 9 <<(result == vec.end() ? " is not present" : "is present")
10 <<endl;

具体实现代码:

 1 #include<iostream>
 2 #include<vector>
 3 #include<algorithm>
 4 using namespace std;
 5 
 6 int main()
 7 {
 8 // value we'll look for
 9    int search_value = 42;
10    int ival;
11    vector<int> vec;
12 
13    while(cin>>ival)
14       vec.push_back(ival);
15    
16    cin.clear();
17 
18 //call find to see if that value is present
19    vector<int>::const_iterator result = find(vec.begin() , vec.end() , search_value);
20 
21 //report the result
22   cout<<"The value "<<search_value
23       <<(result == vec.end() ? " is not present" : "is present")
24       <<endl;
25 
26   return 0;
27 }

 接下来再举一个例子:

 1 #include <algorithm>  
 2 #include <list>  
 3 #include <iostream>  
 4   
 5 using namespace std;  
 6   
 7 int main()  
 8 {  
 9     list<int> ilist;  
10     for (size_t i = 0; i < 10; ++i)  
11     {  
12         ilist.push_back(i+1);  
13     }  
14   
15     ilist.push_back(10);  
16   
17     list<int>::iterator iLocation = find(ilist.begin(), ilist.end(), 10);   //find操作查找等于10的元素,并返回指向该元素的迭代器,如果没有找到,返回指向集合最后一个元素的迭代器
18   
19     if (iLocation != ilist.end())  
20     {  
21         cout << "找到元素 10" << endl;  
22     }  
23   
24     cout << "前一个元素为:" << *(--iLocation) << endl;  
25   
26     return 0;  
27 }  

 

类似地,由于指针的行为与作用在内置数组上的迭代器一样,因此也可以使用find来搜索数组

1 int ia[6] = {27 , 210 , 12 , 47 , 109 , 83};
2 int search_value = 83;
3 int *result = find(ia , ia + 6 , search_value);
4 cout<<"The value "<<search_value
5     <<(result == ia + 6 ? " is not present" : "is present")
6     <<endl;

如果需要传递一个子区间,则传递指向这个子区间的第一个元素以及最后一个元素的下一位置的迭代器(或指针)。

例如,在下面对find函数的调用中,只搜索了ia[1]和ia[2]:

//only search elements ia[1] and ia[2]
int *result = find(ia + 1 , ia + 3 , search_value);

 

二.find_first_of的使用

除了find之外,标准库还定义了其他一些更复杂的查找算法。当中的一部分类似string类的find操作,其中一个是find_first_of函数。

这个算法带有两对迭代器参数来标记两端元素范围:第一段范围内查找与第二段范围中任意元素匹配的元素,然后返回一个迭代器,指向第一个匹配的元素。如果找不到匹配元素,则返回第一个范围的end迭代器。

假设roster1和roster2是两个存放名字的list对象,可使用find_first_of统计有多少个名字同时出现在这两个列表中

 1 size_t cnt = 0;
 2 list<string>::iterator it = roster1.begin();
 3 
 4 // look in roster1 for any name also in roster2
 5 while((it = find_first_of(it , roster1.end() , roster2.begin() , roster2.end())) != roster1.end())
 6 {
 7     ++cnt;
 8     // we got a match , increment it to look in the rest of roster1
 9     ++it;
10 }
11 cout<<"Found "<<cnt
12     <<"  names on both rosters "<<endl;

调 用find_first_of查找roster2中的每个元素是否与第一个范围内的元素匹配,也就是在it到roster1.end()范围内查找一个元 素。该函数返回此范围内第一个同时存在于第二个范围中的元素。在while的第一次循环中,遍历整个roster1范围。第二次以及后续的循环迭代则只考 虑roster1中尚未匹配的部分。

循环条件检查find_first_of的返回值,判断是否找到匹配的名字。如果找到一个匹配,则使计 数器加1,同时给it加1,使它指向roster1中的下一个元素。很明显可知,当不再有任何匹配时,find_first_of返回 roster1.end(),完成统计。

find_first_of,带有两对迭代器参数。每对迭代器中,两个参数的类型必须精确匹配,但不要求两对之间的类型匹配。特别是,元素可存储在不同类型的序列中,只要这两个序列的元素可以比较即可。

在 上述程序中,roster1和roster2的类型不必精确匹配:roster1可以使list对象,而roster2则可以使vector对象、 deque对象或者是其他后面要学到的序列。只要这两个序列的的元素可使用相等(==)操作符进行比较即可。如果roster1是list< string>对象,则roster2可以使vector<char*>对象,因为string标准库为string对象与char* 对象定义了相等(==)操作符。

 

三.find_if的使用

find_if算法 是find的一个谓词判断版本,它利用返回布尔值的谓词判断pred,检查迭代器区间[first, last)上的每一个元素,如果迭代器iter满足pred(*iter) == true,表示找到元素并返回迭代器值iter;未找到元素,则返回last。

find_if :在序列中找符合某谓词的第一个元素。

函数原型为:

1     template<class InputIterator, class Predicate>  
2        InputIterator find_if(  
3           InputIterator _First,   
4           InputIterator _Last,   
5           Predicate _Pred  
6        );  

举个例子说明如下:

 1 #include <algorithm>  
 2 #include <vector>  
 3 #include <iostream>  
 4   
 5 using namespace std;  
 6   
 7 //谓词判断函数 divbyfive : 判断x是否能5整除  
 8 bool divbyfive(int x)  
 9 {  
10     return x % 5 ? 0 : 1;  
11 }  
12   
13 int main()  
14 {  
15   /*  
16     //初始vector : 方式一 
17     //使用下标方式来操作vector
18     //vector随机访问方便,但插入、删除操作效率非常低
19     vector<int> iVect(20);  
20 
21     for(size_t i = 0; i < iVect.size(); ++i)   //注意:size_t
22     {  
23         iVect[i] = (i+1) * (i+3);  
24     }  
25 
26 */
27     //初始vector :方式二
28     vector<int> iVect;
29     for(vector<int>::size_type i = 0 ; i != 20 ; ++i)
30         iVect.push_back((i+1) * (i + 3));
31      
32 
33     //输出vector里的元素
34     for(vector<int>::iterator iter = iVect.begin() ; iter != iVect.end() ; ++iter)
35         cout<<*iter<<" ";
36     cout<<endl;
37   
38   
39     vector<int>::iterator iLocation;  
40     iLocation = find_if(iVect.begin(), iVect.end(), divbyfive);  
41   
42     if (iLocation != iVect.end())  
43     {  
44         cout << "第一个能被5整除的元素为:"  
45              << *iLocation << endl                  //打印元素:15                 
46              << "元素的索引位置为:"  
47              << iLocation - iVect.begin() << endl;  //打印索引位置:2  
48     }  
49      
50     return 0;  
51 }  

 

四. adjacent_find算法

adjacent_find算法用于查找相等或满足条件的邻近元素对。其有两种函数原型:一种在迭代器区间[first , last)上查找两个连续的元素相等时,返回元素对中第一个元素的迭代器位置。另一种是使用二元谓词判断binary_pred,查找迭代器区间 [first , last)上满足binary_pred条件的邻近元素对,未找到则返回last。

原型:

 1 <strong>template<class ForwardIterator>  
 2    ForwardIterator adjacent_find(  
 3       ForwardIterator _First,   
 4       ForwardIterator _Last  
 5       );  
 6 template<class ForwardIterator , class BinaryPredicate>  
 7    ForwardIterator adjacent_find(  
 8       ForwardIterator _First,   
 9       ForwardIterator _Last,   
10             BinaryPredicate _Comp  
11    );  
12 </strong> 

举例如下:

 1 #include <algorithm>  
 2 #include <list>  
 3 #include <iostream>  
 4   
 5 using namespace std;  
 6   
 7 //判断X和y是否奇偶同性  
 8 bool parity_equal(int x, int y)  
 9 {  
10     return (x - y) % 2 == 0 ? 1 : 0;  
11 }  
12   
13 int main()  
14 {  
15     //初始化链表  
16     list<int> iList;  
17     iList.push_back(3);  
18     iList.push_back(6);  
19     iList.push_back(9);  
20     iList.push_back(11);  
21     iList.push_back(11);  
22     iList.push_back(18);  
23     iList.push_back(20);  
24     iList.push_back(20);  
25   
26     //输出链表  
27     list<int>::iterator iter;  
28     for(iter = iList.begin(); iter != iList.end(); ++iter)  
29     {  
30         cout << *iter << "  ";  
31     }  
32     cout << endl;  
33       
34     //查找邻接相等的元素  
35     list<int>::iterator iResult = adjacent_find(iList.begin(), iList.end());  
36     if (iResult != iList.end())  
37     {  
38         cout << "链表中第一对相等的邻近元素为:" << endl;  
39         cout << *iResult++ << endl;  
40         cout << *iResult << endl;  
41     }  
42   
43     //查找奇偶性相同的邻近元素  
44     iResult = adjacent_find(iList.begin(), iList.end(), parity_equal);  
45     if (iResult != iList.end())  
46     {  
47         cout << "链表中第一对奇偶相同的元素为:" << endl;  
48         cout << *iResult++ << endl;  
49         cout << *iResult << endl;  
50     }  
51     return 0;  
52 }  

 

总结:

find()            :  在序列中找某个值的第一个出现

find_if()         :    在序列中符合某谓词的第一个元素

find_first_if     :    在两个序列中找匹配元素

adjacent_find : 用于查找相等或满足条件的邻近元素对

 

img_e00999465d1c2c1b02df587a3ec9c13d.jpg
微信公众号: 猿人谷
如果您认为阅读这篇博客让您有些收获,不妨点击一下右下角的【推荐】
如果您希望与我交流互动,欢迎关注微信公众号
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。

目录
相关文章
|
8天前
|
存储 算法 安全
基于红黑树的局域网上网行为控制C++ 算法解析
在当今网络环境中,局域网上网行为控制对企业和学校至关重要。本文探讨了一种基于红黑树数据结构的高效算法,用于管理用户的上网行为,如IP地址、上网时长、访问网站类别和流量使用情况。通过红黑树的自平衡特性,确保了高效的查找、插入和删除操作。文中提供了C++代码示例,展示了如何实现该算法,并强调其在网络管理中的应用价值。
|
6天前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
10天前
|
编译器 C语言 C++
【c++丨STL】list模拟实现(附源码)
本文介绍了如何模拟实现C++中的`list`容器。`list`底层采用双向带头循环链表结构,相较于`vector`和`string`更为复杂。文章首先回顾了`list`的基本结构和常用接口,然后详细讲解了节点、迭代器及容器的实现过程。 最终,通过这些步骤,我们成功模拟实现了`list`容器的功能。文章最后提供了完整的代码实现,并简要总结了实现过程中的关键点。 如果你对双向链表或`list`的底层实现感兴趣,建议先掌握相关基础知识后再阅读本文,以便更好地理解内容。
16 1
|
13天前
|
算法 安全 C++
用 C++ 算法控制员工上网的软件,关键逻辑是啥?来深度解读下
在企业信息化管理中,控制员工上网的软件成为保障网络秩序与提升办公效率的关键工具。该软件基于C++语言,融合红黑树、令牌桶和滑动窗口等算法,实现网址精准过滤、流量均衡分配及异常连接监测。通过高效的数据结构与算法设计,确保企业网络资源优化配置与安全防护升级,同时尊重员工权益,助力企业数字化发展。
35 4
|
23天前
|
算法 C语言 C++
【c++丨STL】list的使用
本文介绍了STL容器`list`的使用方法及其主要功能。`list`是一种双向链表结构,适用于频繁的插入和删除操作。文章详细讲解了`list`的构造函数、析构函数、赋值重载、迭代器、容量接口、元素访问接口、增删查改操作以及一些特有的操作接口如`splice`、`remove_if`、`unique`、`merge`、`sort`和`reverse`。通过示例代码,读者可以更好地理解如何使用这些接口。最后,作者总结了`list`的特点和适用场景,并预告了后续关于`list`模拟实现的文章。
42 7
|
2月前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
72 4
|
2月前
|
C语言 C++ 容器
【c++丨STL】string模拟实现(附源码)
本文详细介绍了如何模拟实现C++ STL中的`string`类,包括其构造函数、拷贝构造、赋值重载、析构函数等基本功能,以及字符串的插入、删除、查找、比较等操作。文章还展示了如何实现输入输出流操作符,使自定义的`string`类能够方便地与`cin`和`cout`配合使用。通过这些实现,读者不仅能加深对`string`类的理解,还能提升对C++编程技巧的掌握。
85 5
|
2月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
66 2
|
2月前
|
存储 算法 Linux
【c++】STL简介
本文介绍了C++标准模板库(STL)的基本概念、组成部分及学习方法,强调了STL在提高编程效率和代码复用性方面的重要性。文章详细解析了STL的六大组件:容器、算法、迭代器、仿函数、配接器和空间配置器,并提出了学习STL的三个层次,旨在帮助读者深入理解和掌握STL。
65 0
|
26天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
33 0