#include<algorithm>
binary_search
该函数功能是查找指定元素是否存在,存在返回true, 不存在返回false
函数原型:bool binary_search(iterator beg, iterator end, value);
注意:该函数内部通过二分查找实现,二分查找法查找效率很高,但是查找的容器中元素必须的有序序列,所以一定要从小到大排序后进行查找。
实例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
vector<int> vec;
for (int i = 0; i < 10; ++i) vec.push_back(i);
bool judge = binary_search(vec.begin(), vec.end(), 5);
if (judge == true) {
cout << "找到了该元素!!" << endl;
}
else {
cout << "没有找到该元素!!" << endl;
}
return 0;
}
lower_bound() 和 upper_bound()
这两个算法用于在已排序序列中执行范围查找。(底层皆基于二分查找)
std::lower_bound
返回第一个大于等于给定值的元素的迭代器,
std::upper_bound
返回第一个大于给定值的元素的迭代器。
如果没找到,返回末尾的迭代器位置。
实例:
#include<iostream>
#include<vector>
#include<algorithm>
int main() {
std::vector<int> vec = {2, 4, 4, 4, 7, 9};
auto low = std::lower_bound(vec.begin(), vec.end(), 4);
auto up = std::upper_bound(vec.begin(), vec.end(), 4);
std::cout << "第一个 4 的位置:" << std::distance(vec.begin(), low) + 1 << '\n';
std::cout << "第一个大于 4 的位置:" << std::distance(vec.begin(), up) + 1 << '\n';
return 0;
}
map/set
这里用法有点不同,拿set举例:
相对于数组以算法的形式使用,set 输入时已经建好树(不需要algorithm头文件), 而algorithm要多一个类似建树的过程。所以 set 有 s.lower_bound(x) 算法,使用该函数肯定 set 快一点
- set::lower_bound(x):返回set中第一个大于或等于 x 的迭代器指针
- set::upper_bound(x):返回set中第一个大于 x 的迭代器指针
实例:
#include<iostream>
#include<map>
#include<vector>
using namespace std;
int main() {
map<int, int> hash;
vector<int> vec{1,2,1,3,4,5,6,4,3,2,5,4,3,2,11};
for (int i : vec) hash[i]++;
map<int, int>::iterator it = hash.lower_bound(10);
cout << "大于等于10的数为:" << it -> first << endl;
cout << "该数有" << it -> second << "个" << endl;
return 0;
}
equal_range
std::equal_range
结合了 lower_bound()
和 upper_bound()
的功能,返回一个范围,表示所有与给定值相等的元素。
equal_range 根据键值,返回一对迭代器的pair对象。如果该键值在容器中存在,则pair对象中的第一个迭代器指向该键关联的第一个实例,第二个迭代器指向该键关联的最后一个实例的下一位置。如果找不到匹配的元素,则pair对象中的两个迭代器都将指向此键应该插入的位置。总之,equal_range返回迭代器位置区间 [ lower_bound, upper_bound )
实例1:
#include <iostream>
#include <algorithm>
#include <vector>
int main ()
{
std::vector<int> vec = {2, 4, 4, 4, 7, 9};
auto range = std::equal_range(vec.begin(), vec.end(), 4);
std::cout<<"范围是从位置 "<<std::distance(vec.begin(),range.first)+1<<"到"
<<std::distance(vec.begin(),range.second)<<'\n';
return 0;
}
参考代码.first和.second都加了1,但输出结果不对;而只给.first+1,结果就对了。
我想是因为equal_range返回迭代器位置区间 [ lower_bound, upper_bound ) 左闭右开
实例2:
#include <iostream>
#include <map>
int main ()
{
std::multimap<char,int> my_multimap;
my_multimap.insert(std::make_pair('a',10));
my_multimap.insert(std::make_pair('a',20));
my_multimap.insert(std::make_pair('a',30));
my_multimap.insert(std::make_pair('a',40));
my_multimap.insert(std::make_pair('b',10));
my_multimap.insert(std::make_pair('c',10));
my_multimap.insert(std::make_pair('c',20));
std::cout << my_multimap.size() << std::endl;
std::pair<std::multimap<char,int>::iterator,std::multimap<char,int>::iterator> ret;
ret=my_multimap.equal_range('a');
for(std::multimap<char,int>::iterator it=ret.first;it !=ret.second;it++){
std::cout << it->first << " => " << it->second << '\n';
}
return 0;
}
输出:
7
a => 10
a => 20
a => 30
a => 40
从上面例子可以看出,使用了multimap是可以存储重复的键值的,所以使用equal_range开始找’a’键,发现满足条件的有4个,这时返回2个迭代器,第一个迭代器是’a’:10这一组键值对,第二个迭代器是最后一个’a’:40这组满足条件的键值对的后一个键值对’b’:10。因此迭代打印时就会得到一堆输出。
如果没有找到满足条件的键值,那么就会返回最应该插入的位置,这时第一个迭代器和第二个迭代器是相等的。
如果是用map,那么键唯一,也就是将上述代码中的multimap被替换为map,这时下面代码所得到的结果就是’a’键对应的值10。
#include <iostream>
#include <map>
int main ()
{
std::map<char,int> my_map;
my_map.insert(std::make_pair('a',10));
my_map.insert(std::make_pair('a',20));
my_map.insert(std::make_pair('a',30));
my_map.insert(std::make_pair('a',40));
my_map.insert(std::make_pair('b',10));
my_map.insert(std::make_pair('c',10));
my_map.insert(std::make_pair('c',20));
std::cout << my_map.size() << std::endl;
std::pair<std::map<char,int>::iterator,std::map<char,int>::iterator> ret;
ret=my_map.equal_range('a');
for(std::map<char,int>::iterator it=ret.first;it !=ret.second;it++){
std::cout << it->first << " => " << it->second << '\n';
}
return 0;
}
输出:
3
a => 10
find
find函数里面有三个参数,find(begin,end,value)
前两个是迭代器,是容器的开始和结尾,后一个是所要查找的值
即在容器[begin, end)区间内,寻找是否有指定的value值的元素,如果有,返回该元素的迭代器,没有则返回end;所以find返回值也是一个迭代器;
看一下find的底层实现
可以看出来,find内部其实是通过一个for循环来执行的;
实例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
vector<int> vec;
for (int i = 1; i < 11; ++i) vec.push_back(i);
vector<int>::iterator it = find(vec.begin(), vec.end(), 6);
if (it != vec.end()) {
cout << "找到了" << *it << "这个数,下标为:" << it - vec.begin() << endl;
}
else {
cout << "没有找到该数" << endl;
}
return 0;
}
find_if
find_if 就是按条件查找元素,就是把vaule换成了一个判断条件,通过这个条件找相应的数;
find_if(iterator begin, iterator end, _Pred);
找到返回指定位置迭代器,找不到返回结束迭代器位置,begin是开始迭代器,end是结束迭代器,_Pred是 函数或者谓词(返回bool类型的仿函数)
实例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool greaterSix (int n) {
return n > 6;
}
int main() {
vector<int> vec;
for (int i = 1; i < 11; ++i) vec.push_back(i);
vector<int>::iterator it = find_if(vec.begin(), vec.end(), greaterSix);
if (it != vec.end()) {
cout << "找到了" << *it << "这个数大于6,下标为:" << it - vec.begin() << endl;
}
else {
cout << "没有找到该数" << endl;
}
/*auto iit = upper_bound(vec.begin(), vec.end(), 6);
if (iit != vec.end()) {
cout << "找到了" << *iit << "这个数大于6,下标为:" << it - vec.begin() << endl;
}
else {
cout << "没有找到该数" << endl;
}*/
return 0;
}
在代码中注释的部分,使用了函数upper_bound,这个函数功能和用例里的find_if实现一样,都是找大于6的数,返回的也是迭代器。
find_if 的第三个参数也就是判断条件我们是可以通过 函数 或者 仿函数 自己随意定义的,这就相对于upper_bound会有更多样的判断形式;而upper_bound的底层实现是二分法,这比 find_if 的单纯for循环效率要高。所以要根据不同情况使用不同的算法函数。
adjacent_find
adjacent_find 可以查找相邻重复元素,并返回第一个元素的迭代器,找不到返回end
函数原型:adjacent_find(iterator begin, iterator end);
看一下底层实现:
就是一个 while 循环不断更新 next 和 first,next 是 first 的下一个元素,直到 next 和 first 相等时返回 first,如果没有找到就返回了 last
实例:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
vector<int> vec;
vec.push_back(1);
vec.push_back(3);
vec.push_back(4);
vec.push_back(4);
vec.push_back(5);
vector<int>::iterator it = adjacent_find(vec.begin(), vec.end());
if (it != vec.end()) {
cout << "找到了重复元素" << *it << ",第一个下标为:" << it - vec.begin() << endl;
}
else {
cout << "没有找到该重复元素" << endl;
}
return 0;
}
find_first_of和find_last_of
- find_first_of 找第一个符合条件的位置
- find_last_of 找最后一个符合条件的位置
以find_first_of为例
find_first_of 有两种形式:
InputIterator find_first_of (InputIterator beg, InputIterator end,
ForwardIterator searchBeg, ForwardItrerator searhcEnd)
InputIterator find_first_of (InputIterator beg, InputIterator end,
ForwardIterator searchBeg, ForwardItrerator searhcEnd,
BinaryPredicate op)
- 无op版本,返回同时在区间[beg,end)和[sbeg,send)出现的第一个元素位置的迭代器,同时我们可以采用逆向迭代器获得最后一个元素,未发现则end
- 有op版本,返回区间[beg,end)中第一个能与[sbeg,send)内其中一个元素使得op(elem,selem)为真的元素位置的迭代器,未发现则end
- 注意, op 不应在函数调用过程中改变状态 (state)。
- op 不应改动传入的实参。
- 你可以使用 reverse iterator 查找最后一个符合条件的元素。
- 复杂度:线性。至多比较(或调用 op())共 numElems * numSearchElems 次。
op推荐采用lambdas表达式:lambdas的使用方法
实例1:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
//寻找第一个同时在c1,c2出现的元素
vector<int>c1 = {1,2,3,4,5,6,7,8,9 };
vector<int>c2 = {3,4,5,6,7};
auto it = find_first_of(c1.begin(), c1.end(), c2.begin(), c2.end());
if (it != c1.end())
//返回满足条件的元素距离首部的距离
cout << distance(c1.begin(),it)+1<< endl;
else
cout << "未发现" << endl;
}
实例2:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
//寻找最后一个同时在c1,c2出现的元素
vector<int>c1 = {1,2,3,4,5,6,7,8,9 };
vector<int>c2 = {3,4,5,6,7};
auto it = find_first_of(c1.rbegin(), c1.rend(), c2.begin(), c2.end());
if (it != c1.rend())
//返回满足条件的元素距离首部的距离
cout << distance(c1.begin(),it.base())<< endl;
else
cout << "未发现" << endl;
}
实例3:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool oopp(int x,int y){
if(x>6&&y>6&&x==y) return true;
else return false;
}
int main()
{
//寻找第一个同时在c1,c2出现的元素且该元素大于6
vector<int>c1 = {1,2,3,4,5,6,7,8,9 };
vector<int>c2 = {5,6,10,9,8};
auto it = find_first_of(c1.begin(), c1.end(), c2.begin(), c2.end(),oopp);
if (it != c1.end())
//返回满足条件的元素距离首部的距离
cout << distance(c1.begin(),it)+1<< endl;
else
cout << "未发现" << endl;
}
实例4:
示例代码中使用了两个 vector 容器,制成其他容器也是可以的。只要元素的数据类型一致,可以做 == 操作就行。
另外,代码中还演示了 两个 Vector 合并 Insert() 的用法,以及使用 for_each() 打印元素的用法。
#include <iostream>
#include <algorithm>
int main() {
std::vector<int> vt1{1,2,3,4,5,6,7,8,9,10};
std::vector<int> vt2{0,2,6,9};
std::cout << "container 1: ";
for_each(vt1.cbegin(), vt1.cend(), [](int elem){std::cout << elem << ' ';});
std::cout <<std::endl;
std::cout << "container 2: ";
for_each(vt2.cbegin(), vt2.cend(), [](int elem){std::cout << elem << ' ';});
std::cout <<std::endl;
std::vector<int>::iterator pos;
pos = std::find_first_of(vt1.begin(), vt1.end(), vt2.begin(), vt2.end());
if (pos != vt1.end())
{
std::cout << "first element of vt2 in vt1 is element: " << std::distance(vt1.begin(), pos) + 1;
vt1.insert(vt1.end(), vt2.begin(), vt2.end());
std::cout <<std::endl;
std::cout << "container 1: ";
for_each(vt1.cbegin(), vt1.cend(), [](int elem){std::cout << elem << ' ';});
std::cout <<std::endl;
}
}
下面的代码片段是使用 reverse iterator 的示例:
std::vector<int>::reverse_iterator rpos;
rpos = std::find_first_of(vt1.rbegin(), vt1.rend(), vt2.begin(), vt2.end());
std::cout<< "last element of vt2 in vt1 is element:" << std::distance(vt1.begin(), rpos.base());
count 和 count_if
count
可以统计元素个数,返回值为 int 类型,
函数原型:count(iterator beg, iterator end, value);
前两个参数规定了区间,最后一个所需要统计的元素;
底层实现非常简单,就是一个for循环遍历区间,找到一个元素加一,直到结束,所以效率也不是特别高
count_if
这个是在统计一个元素个数的前提下加入了条件,就是按条件统计元素个数,返回值是 int 类型;
函数原型:count_if(iterator beg, iterator end, _Pred);
前两个参数还是规定的区间,最后一个是一个谓词(即仿函数)或者函数
实例:
#include <iostream>
#include <algorithm>
#include <vector>
int main ()
{
std::vector<int> vec = {2, 4, 4, 4, 7, 9};
int numFours = std::count(vec.begin(), vec.end(), 4);
std::cout << "元素 4 出现了 " << numFours << " 次。";
return 0;
}
search
std::search
用于在一个序列中搜索另一个子序列的第一次出现。
实例:
#include <iostream>
#include <algorithm>
#include <vector>
int main ()
{
std::vector<int> mainSeq = {4, 7, 2, 9, 5};
std::vector<int> subSeq = {7, 2};
auto it = std::search(mainSeq.begin(), mainSeq.end(), subSeq.begin(), subSeq.end());
if (it != mainSeq.end()) {
std::cout << "子序列在主序列中找到了!";
} else {
std::cout << "未找到子序列。";
}
return 0;
}
min_element()和max_element()
std::min_element()的使用方法:
- 查找一个区间内的最小元素:std::min_element(first, last)
- 查找一个区间内的最小元素,并使用自定义比较函数:std::min_element(first, last, comp)
std::max_element()的使用方法:
- 查找一个区间内的最大元素:std::max_element(first, last)
- 查找一个区间内的最大元素,并使用自定义比较函数:std::max_element(first, last, comp)
其中,first和last分别是容器的起始迭代器和终止迭代器,comp是一个可调用对象,用于比较两个元素的大小关系。如果不指定comp,则默认使用<运算符进行比较。
注意:std::min_element()和 std::max_elenent() 返回的是迭代器,指向容器中的最小元素和最大元素。如果需要获取元素的值,可以使用( 运算符对迭代器进行解引用。
实例:
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
auto min_it = std::min_element(v.begin(), v.end()); // 查找最小元素
auto max_it = std::max_element(v.begin(), v.end()); // 查找最大元素
cout<<"最小元素:"<<*min_it<<endl;
cout<<"最大元素:"<<*max_it<<endl;
return 0;
}
当然,简单的可以使用min和max
#include <iostream>
#include <algorithm>
int main() {
int p = 18;
int q = 22;
int r = 15;
std::cout <<"比较p和q两个值"<< std::endl;
std::cout <<"较大值"<<std::max(p,q)<< std::endl;
std::cout <<"较小值"<<std::min(p,q)<< std::endl;
int max_of_three = std::max({p, q, r});
int min_of_three = std::min({p, q, r});
std::cout << "Max of three: " << max_of_three << std::endl;
std::cout << "Min of three: " << min_of_three << std::endl;
return 0;
}
参考博文:
https://blog.csdn.net/YXXXYX/article/details/119866219
https://blog.csdn.net/YXXXYX/article/details/119908496
https://blog.csdn.net/qq_34462436/article/details/108105395
https://blog.csdn.net/qq_66726657/article/details/134475023
https://blog.csdn.net/BTChioa/article/details/134960749
https://blog.csdn.net/kingkee/article/details/103806681
https://blog.csdn.net/weixin_44806268/article/details/105834016