簡體   English   中英

std::deque 在開始時實際上是否有恆定時間插入?

[英]Does std::deque actually have constant time insertion at the beginning?

該標准說:

雙端隊列是支持隨機訪問迭代器 (27.2.7) 的序列容器。 此外,它還支持在開始或結束時進行恆定時間的插入和擦除操作; 在中間插入和擦除需要線性時間。

但是,它還在同一條款中說:

本條款中的所有復雜性要求僅根據對包含對象的操作數量進行說明。 [ 示例: vector<vector<int>>類型的復制構造函數具有線性復雜度,即使復制每個包含的vector<int>的復雜度本身也是線性的。 —結束示例]

這是否意味着在deque<int>的開頭插入可以花費線性時間,只要它對已經在 deque 中的int執行的操作不超過恆定數量,並且插入了新的int object?

例如,假設我們使用“大小為 K 個向量的向量”來實現一個雙端隊列。 似乎每K次我們在開頭插入一次,就必須在開頭添加一個新的size-K向量,因此必須移動所有其他size-K向量。 這意味着開始插入的時間復雜度是分攤的 O(N/K),其中 N 是元素的總數,但 K 是常數,所以這只是 O(N)。 但似乎這是標准允許的,因為移動一個大小為 K 的向量不會移動它的任何元素,並且“復雜性要求”是“僅根據操作數來說明的”對包含的int對象.

標准真的允許這樣做嗎? 還是我們應該將其解釋為具有更嚴格的要求,對所包含對象的操作數量恆定加上恆定的額外時間?

例如,假設我們使用“大小為 K 個向量的向量”來實現一個雙端隊列。

那將不是一個有效的實現。 vector前面插入會使容器中的所有指針/引用無效。 要求deque不會使前面插入的任何指針/引用無效。

但是,讓我們暫時忽略它。

但似乎這是標准允許的,因為移動一個大小為 K 的向量不會移動它的任何元素,並且“復雜性要求”是“僅根據操作數來說明的”對包含的 int 對象.

是的,這是允許的。 實際上, deque的實際實現與此並沒有太大的不同(盡管出於明顯的原因它們不使用std::vector本身)。 deque實現的大致輪廓是指向塊的指針數組(前后都有增長空間),每個塊包含最多 X 個項目以及指向下一個/前一個塊的指針(使單個-元素迭代快)。

如果在前面或后面插入足夠多的元素,則塊指針數組必須增長。 這將需要一個相對於deque中的項目數線性時間的操作,但實際上並不對項目本身進行操作,因此它不計算在內。 該規范沒有說明該操作的復雜性。

如果沒有這個規定,我不確定deque的獨特功能集(快速前/后插入隨機訪問)是否可以實現。

我認為您在如何解釋復雜性域的含義方面有所了解。 您試圖區分“線性時間”和“線性復雜性”,我不認為這很有意義。

標准很清楚,前面的插入是恆定時間的,我想我們都同意這一點。 后一段只是告訴我們,每個“恆定”數量的操作在下面所涉及的內容根本不受標准的指定或約束。

這並不罕見。 任何算法都在某種抽象基礎上工作。 即使我們要編寫一個歸結為單個機器指令的算法,並且我們說我們的算法只生成N條機器指令,我們也不會 go 調查每個單獨的復雜性在處理器中具有什么樣的復雜性,並且將其添加到我們的結果中。 我們不會說某些操作最終會在量子分子水平上做得更多,因此我們的O(n)算法實際上是O(N×M 3 )或類似的。 我們選擇不考慮這種抽象級別。 而且,除非所述復雜性取決於算法的輸入,否則完全沒問題。

在您的情況下,移動/復制的內部向量的大小並不真正相關,因為這些不會隨着雙端隊列的增長而改變。 內部向量的數量確實如此,但每個向量的大小是一個獨立的屬性。 因此,在描述將新元素插入外部向量的復雜性時,它是無關緊要的。

實際執行時間(如果您選擇的話,它本身可以用一些算法術語來描述)是否因復制的內部向量的內容而異? 是的當然。 但這與擴展外向量的任務如何隨着外向量本身的增長而增加工作量無關。

所以,這里的標准是當你把另一個放在前面時,它不會復制NN 2甚至記錄 N個內部向量; 據說這些操作的數量不會隨着雙端隊列的增長而改變。 它還說,就該規則而言,它並不關心復制/移動內部向量實際上涉及什么或它們有多大。

復雜性分析與性能無關。 復雜性分析是關於性能如何擴展的。

暫無
暫無

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

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