簡體   English   中英

分割向量的有效方法是什么

[英]What is the efficient way to split a vector

除了使用以下方法以外,是否還有其他固定時間分割向量的方法。

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

這將花費O(N)的復雜性。 在這種情況下,O(end-start)。 是否有固定時間的操作來執行此操作。

還是我為任務使用了錯誤的容器?

這是副本而不是拆分,因此很復雜。 您可能可以為list編寫一個拆分,效果可能會更好。

對於像矢量這樣的容器來說,將元素“放置”在一個連續的內存中,“ 分裂 ”容器的行為必然要求所有內容都需要復制/移動。

list這樣的容器,每個元素都位於其自己的內存塊中,可以很容易地重新排列(請參閱std::list::splice

但是,由於缺少更頻繁的緩存,在非連續內存中包含元素可能會導致較低的內存訪問性能。

換句話說,算法的復雜性可能不是影響性能的唯一因素:不頻繁的線性復制您的損害要小於對分散元素的頻繁線性行走。

權衡主要取決於硬件如何管理緩存以及您使用的std實現如何處理(以及編譯器最終如何進行優化)

std::vector不支持以下操作,但是如果有效的“拆分”操作對您非常重要,則可以編寫自己的容器。 這將是很多工作。

您可以如下定義“ split”:

  • 刪除容器的初始段,並返回包含這些元素的新容器。 對這些元素的引用繼續引用新容器中的相同元素。 舊容器包含其余元素。 新容器的容量等於其大小,而舊容器的容量會因刪除的元素數量而減少。

然后,舊容器和新容器將共享一個底層存儲塊(大概帶有引用計數)。 如果追加新容器,則必須重新分配(因為正在使用緊接其元素末尾的內存),但是只要這種情況很少發生或永遠不會成功就可以。

您的示例代碼將獲得一個副本,但是它不會修改原始容器。 如果需要邏輯副本,則無需實際復制元素就可以做到這一點,您需要COW或不可變對象。

std::list具有一個splice()函數,該函數可以將一系列元素從一個列表移動到另一個列表。 這樣可以避免復制元素,但是從C ++ 11開始,實際上可以保證它不是O(1) ,因為它需要計算已移動了多少個元素。 在C ++ 03中,實現可以選擇是否希望此op為O(1)list::size()O(1) ,但在C ++ 11中, size()必須是所有對象的恆定時間容器。

不過,將std::vectorstd::list的性能進行比較通常不僅僅涉及一項操作。 您必須考慮該list沒有隨機訪問迭代器,依此類推。

創建新的std::vector必然需要復制,因為不允許vector共享其實現的一部分。 從中獲取startend的容器中的修改不應影響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的拓撲-任何可能使任何迭代器失效的事物都會破壞自然。

添加或從除開始/結束不同的地方刪除元素到/時,載體必須具有至少O(N)由於所需的內部位移的復雜性。 當您不僅要刪除元素,還要將元素移出時,會出現sme:對於矢量,必須將其復制,因此,每移動一個元素至少要運行1個操作。 這意味着將元素從向量中移出至少為O(N),其中N是移動的元素數。

如果您需要近乎恆定的時間添加/刪除操作(添加或插入一個或多個元素),則應查看列表/鏈接列表容器,其中所有元素和子列表都易於“分離”,尤其是在您知道指針/迭代器。 或樹木,或任何其他動態結構。

完全順便說一句,我感覺到v_SplitVector做什么,但是它來自哪里? 我不記得stdlib或boost中的這種功能/方法嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM