我有一个std::vector<int>
,我想扔掉x的第一个和最后一个元素。仅复制元素不是一种选择,因为它是O(n)
。
是否有类似vector.begin()+=x
的东西让向量刚刚开始并在之前结束?
我也试过
items = std::vector<int> (&items[x+1],&items[0]+items.size()-y);
其中的项目是我的向量,但这给了我bad_alloc
答案 0 :(得分:3)
如果只需要一系列值,则可以将其表示为范围的第一个元素到最后一个元素的一对迭代器。这些可以在固定的时间内获得。
编辑:根据评论中的描述,这似乎是最明智的解决方案。如果你的函数需要一个向量引用,那么你需要重构一下。
其他解决方案:
如果您不需要原始矢量,因此可以修改它,并且元素的顺序不相关,您可以将第一个x
元素与n-x-y...n-y
元素交换,然后删除最后x+y
个元素。这可以在O(x+y)
时间内完成。
如果合适,您可以选择使用std::list
,如果您有子列表的第一个和最后一个节点的迭代器,那么您可以在恒定时间内完成所要求的内容。这还要求您可以修改原始列表,但元素的顺序不会改变。
如果这些不是选项,那么您需要复制并坚持使用O(n)
。
答案 1 :(得分:3)
C ++标准算法适用于范围,而不适用于实际容器,因此您无需提取任何内容:您只需调整正在使用的迭代器范围。
void foo(const std::vector<T>& vec, const size_t start, const size_t end)
{
assert(vec.size() >= end-start);
auto it1 = vec.begin() + start;
auto it2 = vec.begin() + end;
std::whatever(it1, it2);
}
我不明白为什么它需要比这更复杂。
答案 2 :(得分:2)
其他答案是正确的:通常迭代器都可以。
尽管如此,您还可以编写矢量视图。这是一幅草图:
template<typename T>
struct vector_view
{
vector_view(std::vector<T> const& v, size_t ind_begin, size_t ind_end)
: _v(v)
, _size(/* size of range */)
, _ind_begin(ind_begin) {}
auto size() const { return _size; }
auto const& operator[](size_t i) const
{
//possibly check for input outside range
return _v[ i + _ind_begin ];
}
//conversion of view to std::vector
operator std::vector<T>() const
{
std::vector<T> ret(_size);
//fill it
return ret;
}
private:
std::vector<T> const& _v;
size_t _size;
size_t _ind_begin;
}
根据需要公开更多方法(当你想在标准库算法中使用它时,某些迭代器可能是合适的。)
此外,请注意const引用std::vector<T> const& v;
的有效性 - 如果这可能是一个问题,那么应该更好地使用共享指针。
在这里也可以考虑更一般的方法,例如,使用步幅或类似的东西。