vector與deque的比較

與動(dòng)態(tài)數(shù)組相同,能夠在插入或刪除元素時(shí)自動(dòng)調(diào)整自身大小,其存儲(chǔ)由容器自動(dòng)處理,vector
通常占用多于靜態(tài)數(shù)組的空間,因?yàn)橐峙涓嗟膬?nèi)存以管理將來的增長,在每次插入元素的時(shí),僅當(dāng)額外內(nèi)存耗盡時(shí)觸發(fā)重新分配。

如上圖所示,vector
元素放置在連續(xù)存儲(chǔ)中,以便可以使用迭代器訪問和遍歷他們。在vector
是具有兩端擴(kuò)縮功能的序列容器。其存儲(chǔ)方式與vector
相反,deque
的元素不是相接存儲(chǔ)的,是由一段一段等長的連續(xù)空間構(gòu)成的,各段之間并不一定是連續(xù)的。它的典型實(shí)現(xiàn)如下圖所示,通過單獨(dú)分配固定尺寸的序列(對(duì)應(yīng)圖中的數(shù)據(jù)區(qū)),外加額外的登記(對(duì)應(yīng)圖中map
映射區(qū)),map
數(shù)組中存儲(chǔ)的是每段連續(xù)空間的地址,通過映射區(qū)來管理這些一段一段等長的連續(xù)空間,進(jìn)而實(shí)現(xiàn)“整體連續(xù)”的效果。

當(dāng)deque
容器需要在頭部或者尾部增加空間的時(shí)候,它會(huì)申請(qǐng)一段新的連續(xù)空間,同時(shí)在map
數(shù)組的開頭或者結(jié)尾添加指向該空間的指針,由此將deque
元素串接起來。在遇到空間不足的時(shí)候由于deque
可以申請(qǐng)新的連續(xù)空間,原數(shù)據(jù)空間可以保持不變,更新map
即可,所以deque
在涉及到空間擴(kuò)展的時(shí)候,效率遠(yuǎn)高于vector
。
2. 性能比較
2.1 隨機(jī)訪問

由于vector
是連續(xù)存儲(chǔ)的,deque
是分段連續(xù)存儲(chǔ),其隨機(jī)訪問需對(duì)map
數(shù)組進(jìn)行二次指針解引用(可以理解為:deque
隨機(jī)訪問需要先去找到待訪問元素在哪段連續(xù)存儲(chǔ)空間,然后再對(duì)該空間進(jìn)行下標(biāo)訪問),而vector
只有下標(biāo)訪問一次即可。因此在隨機(jī)訪問性能上,vector
略高于deque
,但兩者復(fù)雜度均為常數(shù)O(1)。
2.2 末尾插入/刪除

前面我們說過,vector
的存儲(chǔ)是自動(dòng)管理的,按需擴(kuò)張收縮,vector
通常占用多于靜態(tài)數(shù)組的空間,因?yàn)橐峙涓嗟膬?nèi)存以管理將來的增長,通常情況下vector
在尾部插入元素的復(fù)雜度為O(1),但當(dāng)額外內(nèi)存耗盡的時(shí)候,需要重新分配,此時(shí)重新分配,是需要單獨(dú)再申請(qǐng)一份更大空間,把vector
原有的元素重新放到新申請(qǐng)的空間上,再完成尾部插入,此時(shí)涉及到了新空間的申請(qǐng)、所有元素的移動(dòng)和舊空間的釋放,這種情況下的插入在性能上是災(zāi)難級(jí)別的,因此,總的來說對(duì)于vector
尾部插入的時(shí)間復(fù)雜度為均攤常數(shù)O(1)。
對(duì)于deque
由于存儲(chǔ)空間是分段連續(xù)的,當(dāng)空間不夠的時(shí)候重新申請(qǐng)新的一段空間即可,不會(huì)涉及到舊元素的移動(dòng),其復(fù)雜度度為常數(shù)O(1)。對(duì)于尾部刪除,因?yàn)椴簧婕暗椒峙淇臻g申請(qǐng),因此兩者的復(fù)雜度均在O(1)。
注:
vector
在尾部插入元素的時(shí),新的size()
如果大于capacity()
,那么所有的迭代器和引用(包括end()
迭代器)都會(huì)失效,否則只有end()
迭代器會(huì)失效。而deque
除了迭代器會(huì)失效,而不會(huì)使指向其余元素的指針或引用失效。
2.3 隨機(jī)插入/刪除

vector
在進(jìn)行隨機(jī)插入的時(shí)候,涉及到插入位置到序列尾部這段元素的移動(dòng)(可以理解為這段元素需要整體往后移動(dòng)一位,給新插入元素把位置留出來),隨機(jī)刪除元素同理,因此其隨機(jī)插入/刪除的時(shí)間復(fù)雜度為插入位置與到vector尾部距離成線性O(n)。deque
的擴(kuò)展方式是雙向的,因此其可以根據(jù)插入位置距離頭部或者尾部較近的距離成線性O(n),因此,其性能略勝vector
一丟丟。
注:對(duì)于
vector
隨機(jī)插入,如果新size()
大于舊的capacity()
就會(huì)導(dǎo)致重分配,所有的迭代器和引用都會(huì)失效,否則,只有在插入點(diǎn)前的迭代器和引用會(huì)保持有效。對(duì)于deque
而言,所有迭代器和引用也會(huì)失效,除非插入位置為容器尾部或者頭部,引用不會(huì)失效。
3. 總結(jié)
vector
和deque
的對(duì)比如下表所示:
vectordeque頭文件使用需要包含頭文件<vector>
使用需要包含頭文件<deque>
存儲(chǔ)方式連續(xù)存儲(chǔ)元素包含元素連續(xù)存儲(chǔ)的內(nèi)存快列表隨機(jī)訪問支持,復(fù)雜度為常數(shù)O(1)支持,復(fù)雜度為常數(shù)O(1)末尾插入/末尾刪除元素均攤常數(shù)O(1)常數(shù)O(1)隨機(jī)插入/隨機(jī)刪除元素與到vector
結(jié)尾的距離成線性O(n)線性O(n)
vector
重分配在性能上是有開銷的,如果在使用之前元素的數(shù)量已知,那么可以使用函數(shù)來消除重分配。
deque
的存儲(chǔ)按需自動(dòng)擴(kuò)展及收縮,擴(kuò)展deque
比擴(kuò)張vector
更優(yōu),因?yàn)樗簧婕暗綇?fù)制既存元素到新內(nèi)存位置。但另外一方面,deque
典型地?fù)碛休^大的最小內(nèi)存開銷,所以當(dāng)即使保有一個(gè)元素的時(shí)候,deque
