对于这个答案,我假设您已经提交了an informed decision to use a std::vector over the other containers available。
我真的必须做一个 for 循环来遍历所有元素吗?
不,您不必滚动for-循环来查找元素。在容器中查找元素的惯用方法是使用标准库中的算法。您是否应该自己滚动实际上取决于具体情况。
帮助您做出决定...
备选方案 1:
std::find() 要求有一个适合您的node 数据类型的相等比较器,这可能很简单:
bool operator ==(node const& l, node const& r)
{
return l.data == r.data;
}
然后,给定required node,您可以搜索该元素。这将返回一个 iterator(如果您使用的是普通的旧数组,则返回一个 pointer)。如果你需要index,这需要一点计算:
auto i = std::find(v.begin(), v.end(), required);
if (i != v.end())
{
std::cout << i->data << " found at index " << i - v.begin() << std::endl;
}
else
{
std::cout << "Item not found" << std::endl;
}
备选方案 2:
如果创建node 太昂贵或者您没有相等运算符,更好的方法是使用std::find_if(),它需要一个谓词(这里我使用一个lambda,因为它很简洁,但你可以use a functor like in this answer):
// Alternative linear search, using a predicate...
auto i = std::find_if(v.begin(), v.end(), [](node const& n){return n.data == 444;});
if (i != v.end())
{
std::cout << i->data << " found at index " << i - v.begin() << std::endl;
}
else
{
std::cout << "Item not found" << std::endl;
}
或者有更快的方法吗?
同样,这取决于。 std::find() 和 std::find_if() 以线性时间运行 (O(n)),与您的 for-loop 相同。
也就是说,使用 std::find() 或 std::find_if() 不会涉及对容器的随机访问或索引(它们使用迭代器),但与您的 for-loop 相比,它们可能需要一些额外的代码。
备选方案 3:
如果运行时间很关键并且您的数组已排序(例如使用std::sort()),您可以执行以对数时间运行的二进制搜索(O (日志n))。 std::lower_bound() 实现了对不小于给定值的第一个元素的二进制搜索。不幸的是,它不需要谓词,但需要一个适合您的 node 数据类型的小于比较器,例如:
bool operator <(node const& l, node const& r)
{
return l.data < r.data;
}
调用类似于std::find(),并返回一个迭代器,但需要额外检查:
auto i = std::lower_bound(v.begin(), v.end(), required);
if (i != v.end() && i->data == required.data)
{
std::cout << i->data << " found at index " << i - v.begin() << std::endl;
}
else
{
std::cout << "Item not found" << std::endl;
}
the Algorithms Library 中的这些函数适用于任何提供迭代器的容器,因此从std::vector 切换到另一个容器将是快速且易于测试和维护的。
决定权在你!
[See a demonstration here.]