[英]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::vector
與std::list
的性能進行比較通常不僅僅涉及一項操作。 您必須考慮該list
沒有隨機訪問迭代器,依此類推。
創建新的std::vector
必然需要復制,因為不允許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
的拓撲-任何可能使任何迭代器失效的事物都會破壞自然。
添加或從除開始/結束不同的地方刪除元素到/時,載體必須具有至少O(N)由於所需的內部位移的復雜性。 當您不僅要刪除元素,還要將元素移出時,會出現sme:對於矢量,必須將其復制,因此,每移動一個元素至少要運行1個操作。 這意味着將元素從向量中移出至少為O(N),其中N是移動的元素數。
如果您需要近乎恆定的時間添加/刪除操作(添加或插入一個或多個元素),則應查看列表/鏈接列表容器,其中所有元素和子列表都易於“分離”,尤其是在您知道指針/迭代器。 或樹木,或任何其他動態結構。
完全順便說一句,我感覺到v_SplitVector
做什么,但是它來自哪里? 我不記得stdlib或boost中的這種功能/方法嗎?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.