STL 中常用的查找算法
find 普通查找
函数签名:
template <class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& val);
函数功能:
在指定区间[first,last)
内查找值为 val
的元素,如果找到,返回容器中指向该元素的迭代器,如果没有查找到,返回 last
参数说明:
- first 查找范围的起始位置(迭代器),包含
- last 查找范围的终止位置(迭代器),不包含
- val 查找的值
函数实现:
该函数内部使用 operator== 将单个元素与val进行比较,其内部实现等价于:
template<class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& val)
{
while (first!=last) {
if (*first==val) return first;
++first;
}
return last;
}
应用案例
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
vector<int>v = {4,1,8,2,6};
// 容器第一个元素迭代器
vector<int>::iterator p_begin = v.begin();
cout << *p_begin << endl; // 4
// 容器最后一个元素的下一个位置迭代器
vector<int>::iterator p_end = v.end();
// end往左(前)移动一个位置,指向最后一个元素
cout << *--p_end << endl; // 6
// 此时,v = {4,1,8,2,6},p_begin 指向4,b_end 指向 6
// 假如要在 1 8 2 范围内查找 18
// p_begin 需要再往后移动一位,指向 1
p_begin++;
vector<int>::iterator r1 = find(p_begin, p_end, 18); // 未找到
if (r1 != p_end) {
cout << "找到" << endl;
}
else {
cout << "未找到" << endl;
}
cout << *r1 << endl; // 6 (因为此时的 last 指向 6)
return 0;
}
如果容器内存储的是自定义数据类型,则需要重载 operator==
操作符
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class Student {
public:
string name;
int age;
Student(string name, int age) {
this->name = name;
this->age = age;
}
/*重载 operator== */
bool operator==(const Student& s) {
return this->name == s.name && this->age == s.age;
}
};
int main() {
vector<Student> vs;
vs.push_back(Student("A", 21));
vs.push_back(Student("B", 21));
vs.push_back(Student("A", 22));
vs.push_back(Student("C", 33));
Student s1("A",20);
Student s2("A",21);
vector<Student>::iterator r1 = find(vs.begin(), vs.end(), s2);
if (r1 != vs.end()) {
cout << "找到" << endl;
}
else {
cout << "未找到" << endl;
}
return 0;
}
find_if 按条件查找
函数签名:
template <class InputIterator, class UnaryPredicate>
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred);
功能说明:
在指定区间[first,last)
查找符合指定条件的元素,返回第一个符合条件的元素迭代器,如果没有找到,返回 last。
参数说明:
- first 查找范围的起始位置(迭代器),包含
- last 查找范围的终止位置(迭代器),不包含
- pred 一元谓词,可以是函数指针或者函数对象
函数实现:
函数模板内部实现等价于:
template<class InputIterator, class UnaryPredicate>
InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
while (first!=last) {
if (pred(*first)) return first;
++first;
}
return last;
}
应用案例:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
// 按条件查找函数调用的 一元谓词
class MyCondition {
public:
/*重载函数调用操作符,返回值为 bool,参数只有一个*/
bool operator()(int val) {
// 目标值是否为 7 的倍数
return val % 7 == 0;
}
};
bool check_val(int val) {
return val % 7 == 0;
}
int main() {
vector<int>v = {1,7,17,21,5};
// 传入一元谓词作为查询条件
vector<int>::iterator r = find_if(v.begin(), v.end(), MyCondition());
if (r != v.end()) {
// 找到,如果找到,返回第一个符合条件的
cout << *r << endl; // 7
}
// 传入函数指针作为查询条件
vector<int>::iterator r2 = find_if(v.begin(), v.end(), check_val);
if (r2 != v.end()) {
// 找到,如果找到,返回第一个符合条件的
cout << *r2 << endl; // 7
}
return 0;
}
adjacent_find 查找相邻重复元素
函数签名:
template <class ForwardIterator>
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last);
函数功能:
查找指定区间[first,end) 内的相邻重复元素
参数说明:
- first 查找范围的起始位置(迭代器),包含
- last 查找范围的终止位置(迭代器),不包
函数实现:
函数内部实现等价于:
template <class ForwardIterator>
ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last)
{
if (first != last)
{
ForwardIterator next=first; ++next;
while (next != last) {
if (*first == *next)
return first;
++first; ++next;
}
}
return last;
}
应用案例:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
vector<int> v = {1,2,3,3,4,4,5};
vector<int>::iterator p = adjacent_find(v.begin(),v.end());
// 返回第一个找到的元素迭代器
if (p != v.end()) {
cout << "找到:" << *p << endl; // 找到:3
}
else {
cout << "未找到" << endl;
}
return 0;
}
binary_search 二分查找
函数签名:
template <class ForwardIterator, class T>
bool binary_search (ForwardIterator first, ForwardIterator last, const T& val);
函数功能:
在指定区间内查找某个元素,查找到返回 true,否则返回 false。
二分查找效率很高,但是只能在有序序列中使用
函数参数:
- first 查找范围的起始位置(迭代器),包含
- last 查找范围的终止位置(迭代器),不包含
- val 要查找的值
函数实现:
函数内部实现等价于:
template <class ForwardIterator, class T>
bool binary_search (ForwardIterator first, ForwardIterator last, const T& val)
{
first = std::lower_bound(first,last,val);
return (first!=last && !(val<*first));
}
应用案例:
#include<iostream>
#include<string>
#include<set>
#include<algorithm>
using namespace std;
void printvalue(int v) {
cout << v << " ";
}
int main() {
// 随机种子
srand((unsigned int)time(NULL));
// set容器存储int默认按升序排序
set<int>s;
for (int i = 0; i < 20; i++) {
// [10-100]之间的随机数
int n = rand() % (100 - 10 + 1) + 10;
s.insert(n);
}
for_each(s.begin(), s.end(), printvalue);
// 11 20 22 26 31 33 40 41 44 48 56 62 68 70 75 92 93 95
// 二分查找 33
bool result = binary_search(s.begin(),s.end(),33);
cout << (result?"找到":"未找到") << endl;
}
count 统计元素个数
函数签名:
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type count (InputIterator first, InputIterator last, const T& val);
函数功能:
统计返回指定区间内值等于val的元素个数(如果元素是自定义数据类型,那么需要重写 operator== 操作符)
函数参数:
- first 查找范围的起始位置(迭代器),包含
- last 查找范围的终止位置(迭代器),不包含
- val 要查找的值
函数实现:
函数内部实现等价于:
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count (InputIterator first, InputIterator last, const T& val)
{
typename iterator_traits<InputIterator>::difference_type ret = 0;
while (first!=last) {
if (*first == val) ++ret;
++first;
}
return ret;
}
应用案例:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
class Person {
public:
string name;
int age;
Person(string name, int age) {
this->name = name;
this->age = age;
}
bool operator==(const Person& p) {
return p.name == this->name && p.age == this -> age;
}
};
int main() {
vector<Person>ps;
ps.push_back(Person("zs", 22));
ps.push_back(Person("zs", 22));
ps.push_back(Person("zs", 22));
ps.push_back(Person("zs", 25));
ps.push_back(Person("ls", 33));
ps.push_back(Person("ls", 33));
Person p1("zs",22);
Person p2("ls",33);
cout << "p1个数" << count(ps.begin(), ps.end(), p1) << endl; // p1个数3
cout << "p2个数" << count(ps.begin(), ps.end(), p2) << endl; // p2个数2
return 0;
}
count_if 按条件统计个数
函数签名:
template <class InputIterator, class UnaryPredicate>
typename iterator_traits<InputIterator>::difference_type count_if (InputIterator first, InputIterator last, UnaryPredicate pred);
函数功能:
统计指定区间内符合指定条件的元素个数
函数参数:
- first 查找范围的起始位置(迭代器),包含
- last 查找范围的终止位置(迭代器),不包含
- pred 一元谓词,它可以是函数指针,也可以是函数对象。
函数实现:
函数内部实现等价于:
template <class InputIterator, class UnaryPredicate>
typename iterator_traits<InputIterator>::difference_type
count_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
typename iterator_traits<InputIterator>::difference_type ret = 0;
while (first!=last) {
if (pred(*first)) ++ret;
++first;
}
return ret;
}
应用案例:
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;
bool is_EvenNumber(int val) {
// 判断是不是偶数
return val % 2 == 0;
}
class EvenNumber {
public:
bool operator()(int val) {
// 判断是不是偶数
return val % 2 == 0;
}
};
int main() {
// 随机种子
srand((unsigned int)time(NULL));
vector<int>v(100);
for (int i = 0; i < 100; i++) {
// 生成 [100-999]内的随机整数
int n = rand() % (999 - 100 + 1) + 100;
v.push_back(n);
}
// 统计偶数个数,传入函数指针作为条件
cout << count_if(v.begin(), v.end(), is_EvenNumber) << endl;
// 统计偶数个数,传入函数对象作为条件
cout << count_if(v.begin(), v.end(), EvenNumber()) << endl;
return 0;
}