排序时在空std :: vector上使用insert()

时间:2017-06-08 03:00:43

标签: c++ vector

我理所当然地想要添加std::vector而不用担心我应该使用push_back()。但是我的问题集是我需要一个干净的代码来检查我输入的值是否已经在std::vector中,如果没有,我必须按顺序递增顺序。要做到这一点,我正在做:

vector<Book>::iterator it;
it = std::find(books.begin(), books.end(), b);
if (it != books.end()) {
    *it = b; // if b exists in books, overwrite the iterator
}
else {
    vector<Book>::iterator _it;
    _it = lower_bound(books.begin(), books.end(), b);
    books.insert(_it, b); // here on an empty vector, _it has no values
}

else仅在b中尚未存在值std::vector时才会运行。如果这是针对它检查的第一个值,则else会运行(因为它为空)而std::iterator运行在books[0](?)。

让我谨慎使用的是,在insert()行调试时,_it的值为std::iterator的每个成员读取“错误读取....” {1}}指向。现在程序运行并产生预期的结果,但它是错误的吗?

3 个答案:

答案 0 :(得分:3)

你在做什么工作得很好。然而,它不是最有效的方式。使用std::find并没有利用向量中的数据排序这一事实,它会访问每个元素,直到找到正确的元素。

您可以从头开始使用std::find代替std::lower_bound,因为如果元素存在,它将找到您的元素,如果不存在,它将找到插入新元素的正确位置。

此外,它将使用二进制搜索,因此它的跳跃和界限将比std::find更快。你也不会两次找到插入/替换点。

这样的事情应该做:

void insert_or_replace(std::vector<Book>& books, Book const& b)
{
    std::vector<Book>::iterator it;

    it = std::lower_bound(books.begin(), books.end(), b);

    if(it != books.end() && *it == b)
        *it = b;
    else
        books.insert(it, b);
}

答案 1 :(得分:1)

代码非常好。对于空向量lower_bound(books.begin(), books.end(), b)将返回end()迭代器。将其传递给std::vector::insert将会正常工作。

  

pos - 迭代器,在此之前插入内容。 pos可能是end()迭代器

关于你的担心:

  

使我谨慎使用的是,在insert()行调试时,_it的值读取&#34;错误读取....&#34;对于std::iterator所指向的每个成员。

那是因为end()迭代器指向最后一个元素后面的位置,所以它对它的依赖是无效的(为了得到一个不存在的元素)。

答案 2 :(得分:0)

这是明确定义的行为。

lower_bound将返回结束迭代器(在您的情况下为books.end())为空范围,或者b应该在最后一个元素之后。 insert将在传递给它的迭代器之前添加新元素,因此这将在end之前。在空向量中,这将具有将元素添加到向量的效果。