find、find_if、find_first_of、find_if_not、search、二分查找
1.std::find:搜索等于 value 的元素
中文标准库:find、find_if、find_if_not
- 可能的实现:
template<class InputIt, class T>
InputIt find(InputIt first, InputIt last, const T& value)
{
for (; first != last; ++first)
{
if (*first == value)
{
return first;
}
}
return last;
}
2.std::find_if:搜索函数对象 p 对其返回 true 的元素,返回值是一个迭代器
-
注意:函数对象p必须可以返回值true(如果所有元素都不能使其返回true,则没有查找到符合条件的元素)
-
可能的实现:
template<class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p)
{
for (; first != last; ++first)
{
if (p(*first))
{
return first;
}
}
return last;
}
3.std::find_if_not搜索函数对象 q 对其返回 false 的元素。
- 可能的实现:
template<class InputIt, class UnaryPredicate>
InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q)
{
for (; first != last; ++first)
{
if (!q(*first))
{
return first;
}
}
return last;
}
4.std::find_first_of:在范围 [first, last) 中搜索范围 [s_first, s_last) 中的任何元素。
-
注意:两个容器的类型可以不一样,查找到即返回对应元素的迭代器(后面的元素不会再比较),如下示例
-
算法库中没有find_last_of、find_first_not_of、find_last_not_of这几个函数都是std::string的成员函数
-
可能的实现版本1:
template<class InputIt, class ForwardIt>
InputIt find_first_of(InputIt first, InputIt last,ForwardIt s_first, ForwardIt s_last)
{
for (; first != last; ++first)
{
for (ForwardIt it = s_first; it != s_last; ++it)
{
if (*first == *it)
{
return first;
}
}
}
return last;
}
- 可能的实现版本2
template<class InputIt, class ForwardIt, class BinaryPredicate>
InputIt find_first_of(InputIt first, InputIt last,ForwardIt s_first, ForwardIt s_last,BinaryPredicate p)
{
for (; first != last; ++first)
{
for (ForwardIt it = s_first; it != s_last; ++it)
{
if (p(*first, *it))
{
return first;
}
}
}
return last;
}
- 示例:
#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
int main()
{
std::vector<int> v{ 0, 4,2, 3, 25, 5 };
std::list<int> t{ 6, 19, 10, 3 };
//在v中查找第一个和t中任意一个元素相等的元素,没有找到返回v.end()
auto ret1 = std::find_first_of(v.begin(), v.end(), t.begin(), t.end()); //元素3对应的迭代器
//在v中查找第一个使二元函数对象(另一个二元函数对象的参数为t中的任意一个元素)返回true的元素,没有找到返回v.end()
auto ret2 = std::find_first_of(v.begin(), v.end(), t.begin(), t.end(), [](int i, int j) {return i > j; }); //元素4对应的迭代器
return 0;
}
5.find_end:在范围 [first, last - (s_last - s_first)) 中搜索子序列 [s_first, s_last) 的最后一次出现。
-
该函数依赖std::serach
-
可能的实现版本1:
template<class ForwardIt1, class ForwardIt2>
ForwardIt1 find_end(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last)
{
if (s_first == s_last)
return last;
ForwardIt1 result = last;
while (true)
{
ForwardIt1 new_result = std::search(first, last, s_first, s_last);
if (new_result == last)
break;
else
{
result = new_result;
first = result;
++first;
}
}
return result;
}
- 可能的实现版本2:
template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
ForwardIt1 find_end(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last,BinaryPredicate p)
{
if (s_first == s_last)
return last;
ForwardIt1 result = last;
while (true)
{
ForwardIt1 new_result = std::search(first, last, s_first, s_last, p);
if (new_result == last)
break;
else
{
result = new_result;
first = result;
++first;
}
}
return result;
}
6.std::search:搜索范围 [first, last - (s_last - s_first)) 中元素子序列 [s_first, s_last) 的首次出现。
- 可能的实现1:
template<class ForwardIt1, class ForwardIt2>
ForwardIt1 search(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last)
{
for (; ; ++first)
{
ForwardIt1 it = first;
for (ForwardIt2 s_it = s_first; ; ++it, ++s_it)
{
if (s_it == s_last)
return first; //第二个容器遍历完了,说明找到了子序列[s_first,s_last),返回子序列第一个元素在第一个容器中的位置
if (it == last)
return last; //第一个容器遍历完了,说明没找到子序列,返回第一个容器的end()
if (!(*it == *s_it))
break;//两个容器中的当前要比较的元素不相等,第一个容器要查找的位置加1然后继续比较
}
}
}
- 可能的实现2:
template<class ForwardIt1, class ForwardIt2, class BinaryPredicate>
ForwardIt1 search(ForwardIt1 first, ForwardIt1 last,ForwardIt2 s_first, ForwardIt2 s_last,BinaryPredicate p)
{
for (; ; ++first)
{
ForwardIt1 it = first;
for (ForwardIt2 s_it = s_first; ; ++it, ++s_it)
{
if (s_it == s_last)
return first;
if (it == last)
return last;
if (!p(*it, *s_it))
break;
}
}
}
- std::search_n:在范围 [first, last) 中搜索 count 个相同元素的序列,每个都等于给定的值 value 。内部使用了equal_to
示例代码:
#include <algorithm>
#include <iostream>
#include <vector>
#include <list>
int main()
{
std::vector<int> v{ 0, 4, 2, 3, 25, 5, 2, 3, 25 };
std::list<int> x{ 2, 3, 25 };
std::list<int> y{ 3 ,5 ,3};
auto ret1 = std::find_first_of(v.begin(), v.end(), x.begin(), x.end());
std::cout << *(--ret1); //4
auto ret2 = std::find_first_of(v.begin(), v.end(), y.begin(), y.end());
std::cout << *(--ret2); //2
auto ret3 = std::search(v.begin(), v.end(), x.begin(), x.end());
std::cout << *(--ret3); //4
auto ret4 = std::search(v.begin(), v.end(), y.begin(), y.end()); //end()
auto ret5 = std::find_end(v.begin(), v.end(), y.begin(), y.end()); //end()
auto ret6 = std::find_end(v.begin(), v.end(), x.begin(), x.end());
std::cout << *(--ret6); //5
std::vector<int> v1{ 0,1,0,0,2,0,0,0,3,0,0,0,3,0,0,0,0,4 };
std::list<int> z{ 0,0,0 };
auto ret7 = std::search_n(v1.begin(), v1.end(), 3, 0);
std::cout << *(--ret7); //2
//上下两中方式等价
auto ret9 = std::search(v1.begin(), v1.end(), z.begin(), z.end());
std::cout << *(--ret9); //2
return 0;
}
7.其他查找(比较)算法
函数 | 描述 |
---|---|
std::includes | 若已排序范围 [first2, last2) 是已排序范围 [first1, last1) 的子序列则返回 true 。(子序列不必相接。) |
std::adjacent_find | 查找首对相邻的相同(或满足给定谓词的)元素 |
std::mismatch | 寻找两个范围出现不同的首个位置,返回来自两个范围:一个以 [first1, last1) 定义而另一个以 [first2,last2) 定义,的首个不匹配对 |
std::equal | 确定两个元素集合是否是相同的,如果范围 [first1, last1) 和范围 [first2, first2 + (last1 - first1)) 相等,返回 true ,否则返回 false |
8.二分查找
使用二分查找的容器必须按升序排序
- binary_search:查找某个元素是否出现
在数组中以二分法检索的方式查找,若在数组(要求数组元素非递减)中查找到元素则真,若查找不到则返回值为假。
vector<int> vec{ 9,8,7,6,5,4,3,2,1 };
auto ret = binary_search(vec.begin(), vec.end(), 2); //false,
-
lower_bound 查找第一个大于或等于某个元素的位置
-
upper_bound 查找第一个大于某个元素的位置
-
equal_range 查找等于某值的元素范围
返回值是pair<iterator,iterator>
vector<int> vec{ 1,2,2,2,4,4,4,5,7,8 };
auto ret1 = equal_range(vec.begin(), vec.end(), 3); //找不到则返回两个相同的第一个大于3的位置{4,4}
auto ret2 = equal_range(vec.begin(), vec.end(), 4); //返回第一个等于4和第一个大于4的位置{4,5}
- equal_rangeC++20新增三个ranges::