假设我有一个包含10000个对象的vector<node>
:
vect[0] to vect[9999]
struct node
{
int data;
};
让我们说我想找到包含这个数据的矢量id(“444”),恰好在节点99中。
我是否真的需要 for -loop来循环遍历所有元素然后使用
if (data == c[i].data)
还是有更快的方法吗?请注意我的数据是不同的,不会在其他node
中重复。
答案 0 :(得分:3)
对于这个答案,我假设你已经an informed decision to use a std::vector
over the other containers available。
我是否真的必须使用for循环遍历所有元素?
不,您不必滚动for
- 循环来查找元素。在容器中查找元素的惯用方法是使用标准库中的算法。是否应滚动你自己真的取决于具体情况。
帮助您决定......
std::find()
要求您的node
数据类型有一个合适的相等比较器,可能就像这样简单:
bool operator ==(node const& l, node const& r)
{
return l.data == r.data;
}
然后,给定required
node
,您可以搜索该元素。如果您使用普通旧数组,则返回迭代器(或指针)。如果您需要索引,则需要进行一些计算:
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;
}
如果创建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 ))运行,与{{1}相同}} - 环
也就是说,使用for
或std::find()
不会涉及对容器的随机访问或索引(它们使用迭代器),但与{{1}相比,它们可能需要一些额外的代码}}环
如果运行时间非常重要并且您的数组已排序(例如std::sort()
),则可以执行二进制搜索,该搜索以对数时间运行( O (log n ))。 std::lower_bound()
实现对不小于给定值的第一个元素的二进制搜索。不幸的是,它不需要谓词,但需要适合您std::find_if()
数据类型的小于比较器,例如:
for-
调用类似于node
并返回迭代器,但需要额外检查:
bool operator <(node const& l, node const& r)
{
return l.data < r.data;
}
the Algorithms Library中的这些函数可以处理任何提供迭代器的容器,因此从std::find()
切换到另一个容器可以快速,轻松地进行测试和维护。
决定权归您所有!
答案 1 :(得分:0)
您应该使用std::find
。如果你事先对矢量一无所知(比如它被排序),你就不能比线性复杂度(O(n)
)更快。
答案 2 :(得分:0)
如果要在容器中查找元素,则vector
不是正确的数据结构。您应该使用有序的容器,例如std::set
或std::map
。由于这些容器中的元素保持有序(排序),我们可以在O(log (n))
时间内找到元素,而不是无序容器的线性时间。
答案 3 :(得分:0)
使用std::find
:
vector<int>::Iterator it = find (vect.begin(), vect.end(), 444);
请注意,如果您已对矢量进行了排序,则可以加快速度。
答案 4 :(得分:0)
一个简洁的解决方案是在int index
结构中添加一个额外的node
成员,以便在拥有结构实例时提供数据到索引的映射。在这种情况下,您应该将std::vector
包装在NodeVector
类中,该类将处理索引的更新,例如,当您删除项目时(它足以从元素的索引中减去1)在这种情况下被删除的元素)等。如果向量不改变元素的数量,那甚至不是问题。除此之外,如果您不能让struct的实例大小增加,请使用std::map
。迭代收集器找到一个项目并不是很聪明,除非你很少需要这样做并且制造任何复杂的东西并不值得这么麻烦。