分割矢量的有效方法是什么?

时间:2013-02-08 08:22:35

标签: c++ vector

除了使用以下内容之外,还有其他任何时间方法来分割矢量。

 std::vector<int> v_SplitVector(start , end);

这将需要O(N)的复杂性。在这种情况下O(结束 ​​- 开始)。是否有恒定的时间操作。

我使用了错误的容器来完成任务吗?..

5 个答案:

答案 0 :(得分:3)

这是一个副本而不是分裂,因此复杂。您可以为list编写一个可能表现更好的分组。

答案 1 :(得分:3)

拆分”容器的行为,对于像矢量这样的容器,其中元素位于连续的内存中,需要复制/移动所有需要在另一端的内容。

list这样的容器,每个容器都有自己的内存块,可以很容易地重新排列(参见std::list::splice

但是,由于更频繁的缓存丢失,在非连续内存中使用元素可能会导致内存访问性能降低。

换句话说,算法的复杂性可能不是影响性能的唯一因素:不常见的线性副本可能损坏,而不是频繁的分散元素线性行走。

权衡取决于硬件如何管理缓存以及您使用的std实现如何处理(以及编译器最终如何优化)

答案 2 :(得分:2)

std::vector不支持以下内容,但如果高效的“拆分”操作对您来说非常重要,那么您可以编写自己的容器。这将是相当多的工作。

您可以按如下方式定义“拆分”:

  • 删除容器的初始段,并返回包含这些元素的新容器。对这些元素的引用继续引用新容器中的相同元素。旧容器包含其余元素。新容器的容量等于其容量,旧容器的容量因删除的元素数量而减少。

然后旧容器和新容器将共享一个底层存储块(可能是重新计数)。如果你追加它,新容器将不得不重新分配(因为它的元素末尾的内存正在使用中),但只要这种情况很少发生或永远不会是胜利。

您的示例代码需要一份副本,但它不会修改原始容器。如果需要逻辑副本,那么在不实际复制元素的情况下执行它,您需要COW或不可变对象。

std::list有一个splice()函数,可以将一系列元素从一个列表移动到另一个列表。这避免了复制元素,但从C ++ 11开始,它实际上保证不是O(1),因为它需要计算它移动了多少元素。在C ++ 03中,实现可以选择是否希望此操作为O(1)list::size()O(1),但在C ++ 11 size()中需要保持不变所有容器的时间。

std::vectorstd::list的效果进行比较通常不仅仅是一项操作。您必须考虑list没有随机访问迭代器,依此类推。

答案 3 :(得分:2)

创建新的std::vector必然需要复制,因为 不允许向量共享其实现的部分内容。 您从中获得start容器的修改 并且end不应影响splitVector中的值。

您可以轻松地创建一个View容器, 它只保存两个迭代器,并映射所有访问 通过他们。有点像:

template <typename Iterator>
class View
{
    Iterator myBegin;
    Iterator myEnd;
public:
    typedef typename std::iterator_traits<Iterator>::value_type value_type;
    //  And the other usual typedefs, including...
    typedef Iterator iterator;

    View( Iterator begin, Iterator end )
        : myBegin( begin )
        , myEnd( end )
    {
    }

    iterator begin() { return myBegin; }
    iterator end()   { return myEnd; }
    value_type operator[]( ptrdiff_t index ) { return *(myBegin + index ); }
    //  ...
};

这需要相当数量的样板,因为 像vector这样的东西的界面相当完整,但它是 一切都非常直接和简单。你不能做的一件事 但是,要做的是修改其中的拓扑 底层容器或任何View - 任何可能的东西 当然,使任何迭代器失效都会造成破坏。

答案 4 :(得分:0)

在不同于开始/结束的位置添加元素或从中删除元素时,由于需要内部移位,向量必须至少具有o(n)的复杂度。如果您不仅要移除元素,而且要移出元素,则会出现以下情况:对于向量,必须复制它们,因此,每个元素移动至少1个操作。这意味着从向量中移动元素至少为O(N),其中N是移动元素的数量。

如果你需要近乎恒定的时间添加/删除操作(无论是添加/插入一个或多个元素),你应该查看list / linkedlist容器,其中所有元素和子列表都很容易“可拆卸”,特别是如果你知道的话指针/迭代器。或树木,或任何其他动态结构。

完全顺便说一下,我感觉v_SplitVector做了什么,但是它来自哪里?我不记得stdlib或boost中的这种函数/方法吗?