使用std :: find()和反向迭代器

时间:2017-03-07 02:13:06

标签: c++ c++11

我在理解如何使用std::find()函数的反向迭代器方面遇到了一些麻烦。我相信如果我能看到一个完成以下任务的例子,我就能完全理解它。

所以,假设我想要搜索std::vector;但是,我不想搜索典型的方式。我想找到第一次出现的值从某个索引开始并朝向向量的开头。举例说明:


    3 | 4 | 7| 4| 2| 6| 3|
    ^             ^
    |<------------| 
             start_point

搜索:在给定上述搜索布局的情况下,找到第一个出现的4

预期结果:指数3

我很确定在这种情况下必须使用反向迭代器,但我无法弄清楚如何去做。

3 个答案:

答案 0 :(得分:5)

首先设置起始位置:

auto it = v.rbegin() + 2;  // two from the end

然后搜索:

auto kt = std::find(it, v.rend(), 4);

如果kt == v.rend(),则找不到任何元素;否则我们可以通过简单的距离计算从前面计算索引:

if (kt == v.rend()) {
  std::cerr << "Element 4 not found.\n";
  std::abort();
} else {
  auto n = std::distance(kt, v.rend()) - 1;
  std::cout << "Element 4 found at position v[" << n << "].\n";
}

答案 1 :(得分:4)

如果您正在使用std::vector或任何其他提供随机访问迭代器的容器,您可以使用算术推进迭代器,就像使用指针一样。你的示例向量有7个元素,你想从索引5开始,所以你可以得到一个正常的迭代器到那个元素:

auto i = v.begin() + 5;

对于反向迭代器,你从向量的后面开始,而不是从前面开始,所以为了获得正确的偏移,你必须从大小中减去所需的索引,如下所示:

auto i = v.rbegin() + (v.size() - 5);

在你的例子中,这将是2,所以反向迭代器将开始指向最后一个元素,然后向开头移动两个空格,到达你想要的起点。

然后,您可以按正常方式使用std::find

auto found = std::find(v.rbegin() + (v.size() - 5), v.rend(), 4);
if(found == v.rend()) {
    std::cout << "No element found." << std::endl;
} else {
    std::cout << "Index " << (v.rend() - found) << std::endl;
}

请记住,在测试std::find的结果以查看是否找到任何内容时,您需要使用rend(),而不是end()。当您将反向迭代器与普通迭代器进行比较时,您需要比较实际位置,而不是开始时的偏移量,因此v.rend() != v.end()

如果您没有随机访问迭代器(例如,在std::list中),则无法使用指针式算术,因此您可以使用std::advance来提升迭代器到特定位置,std::distance来获取两个迭代器之间的距离。

答案 2 :(得分:2)

尝试类似以下内容

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

int main()
{
    std::vector<int> v = { 3, 4, 7, 4, 2, 6, 3 };
    std::vector<int>::size_type pos = 4;

    auto it = std::find(std::next(v.rbegin(), v.size() - pos), v.rend(), 4);

    if (it != v.rend())
    {
        std::cout << std::distance(v.begin(), it.base() - 1) << std::endl;
    }

}