如何通过C ++中的数据获取向量索引?

时间:2013-02-16 20:52:59

标签: c++ search vector

假设我有一个包含10000个对象的vector<node>

vect[0] to vect[9999]

struct node
{
    int data;
};

让我们说我想找到包含这个数据的矢量id(“444”),恰好在节点99中。

我是否真的需要 for -loop来循环遍历所有元素然后使用

if (data == c[i].data)

还是有更快的方法吗?请注意我的数据是不同的,不会在其他node中重复。

5 个答案:

答案 0 :(得分:3)

对于这个答案,我假设你已经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,您可以搜索该元素。如果您使用普通旧数组,则返回迭代器(或指针)。如果您需要索引,则需要进行一些计算:

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 ))运行,与{{1}相同}} - 环

也就是说,使用forstd::find()不会涉及对容器的随机访问或索引(它们使用迭代器),但与{{1}相比,它们可能需要一些额外的代码}}环

备选方案3:

如果运行时间非常重要并且您的数组已排序(例如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()切换到另一个容器可以快速,轻松地进行测试和维护。

决定权归您所有!

[See a demonstration here.]

答案 1 :(得分:0)

您应该使用std::find。如果你事先对矢量一无所知(比如它被排序),你就不能比线性复杂度(O(n))更快。

答案 2 :(得分:0)

如果要在容器中查找元素,则vector不是正确的数据结构。您应该使用有序的容器,例如std::setstd::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。迭代收集器找到一个项目并不是很聪明,除非你很少需要这样做并且制造任何复杂的东西并不值得这么麻烦。