概述
在编码中经常会遇到一种场景,就是要在数组或列表中查找某个元素是否存在,其实对于这种线性操作,自己实现一个循环来检查是非常简单的事情,那既然这样,为啥还要专门写篇博客来分享呢?
一个最重要的原因就是我们原本就可以用更简洁直观高效的方式去替代手写for循环,这个方式就是使用C++标准库函数。
再啰嗦几句。
通常在面试的时候,为了考察面试者的编码功底,会让其从头实现某些基础的算法,但是在实际开发中,很多东西都有现成的封装。只有把语言、标准库“双剑合璧”才能算是真正的C++。而且据C++标准委员会的安排,今后C++也会更侧重于扩充库而不是扩充语言,可见其分量的轻重了。
总之,C++标准库是一个非常强大的东东,并且实现这些标准库的人都是些非常牛逼的顶级程序员,性能都是最优的。所以不要总想着所有事情都亲力亲为的去写一遍,既浪费时间,写出来的东西可能还很菜。那么,这里就通过一些简单的示例来演示如何通过标准库函数来实现。
正文
如何检查vector中是否包含给定元素。
std::count
最简单的方式是对vector中的指定元素进行计数,如果count不为零,表示该元素存在,那么std::count可以很容易实现。
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> v = { 1, 20, 2, 6, 3, 7 }; int key = 6; if (std::count(v.begin(), v.end(), key)) std::cout << "Element found"; else std::cout << "Element not found"; return 0; }
std::find
相比第一种方式,std::find()算法能够更快速的查找给定范围内的值,因为std::count()会变量整个容器以获得元素计数,而find()在找到匹配元素后就立即停止搜索。
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> v = { 1, 20, 2, 6, 3, 7 }; int key = 6; if (std::find(v.begin(), v.end(), key) != v.end()) std::cout << "Element found"; else std::cout << "Element not found"; return 0; }
std::find_if
和find相似的还有一个叫 std::find_if()算法,如果查找需要满足某些条件,那么推荐使用该方法。这里我们可以结合lambda来使用,非常简洁。
比如,要查找列表中是否有元素能被5整除
#include <iostream> #include <vector> #include <algorithm> int main() { auto lst = {1,4,9,5,11}; if(std::find_if(lst.begin(),lst.end(),[](auto v){ if(v%5 ==0) return true; else return false; }) != lst.end()){ std::cout << "Element found"; } else{ std::cout << "Element not found"; } return 0; }
C++ 11 - std::any_of
该算法与std::find_if相似,但不是返回满足条件的的序列中第一个元素的迭代器,而是如果任何元素满足条件后返回true,否则返回false。
#include <iostream> #include <vector> #include <algorithm> struct compare { int key; compare(int const &i): key(i) { } bool operator()(int const &i) { return (i == key); } }; int main() { std::vector<int> v = { 4, 7, 5, 2, 6, 9 }; int key = 6; if (std::any_of(v.begin(), v.end(), compare(key))) std::cout << "Element found"; else std::cout << "Element not found"; return 0; }
或者直接修改find_of的案例:
int main() { auto lst = {1,4,9,5,11}; if(std::any_of(lst.begin(),lst.end(),[](int v){ if(v%5 ==0) return true; else return false; })){ std::cout << "Element found"; } else{ std::cout << "Element not found"; } return 0; }
C++ 11 - std::none_of
该算法刚好和any_of相反,如果给定的条件在范围内所有元素都返回false,则返回true,如果至少一个元素返回true,则返回false。
直接修改上述示例,将if条件改成“非”就可以了,不再赘述。
std::binary_search
最后一种方法,如果vector是有序的,那么可以考虑使用这种算法,如果在给定范围内找到元素,则返回true,否则返回false。该方式是采用二分法查找,时间复杂度为O(log(n)),速度比较快。
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> v = { 1, 2, 3, 4, 5, 6, 7 }; int key = 4; if (std::binary_search(v.begin(), v.end(), key)) std::cout << "Element found"; else std::cout << "Element not found"; return 0; }
OK,以上所有方法都可以实现我们想要的结果,只是在不同情况下选择一种自己喜欢的方式即可。
附:
C++接口文档:https://en.cppreference.com/w/
C++算法库介绍:https://en.cppreference.com/w/cpp/algorithm