deque是一個動態數組,deque與vector非常類似,vector是一個單向開口的連續線性空間,deque則是雙向開口的連續線性空間。兩者唯一的區別是deque可以在數組的開頭和末尾插入和刪除數據,而vector只能在末尾插入刪除數據(當然,從技術層面上,vector也可以從首尾兩端進行操作,但是其從頭部操作效率奇差,無法接受)。
deque示意圖
實質:
deque(包含頭文件#include<deque>)由若干段連續空間串接而成,一旦有必要在deque的頭部或尾端增加新的空間,便配置一段定量連續的空間,串接在deque的頭部或尾端。deque的最大任務,就是在這些分段連續的空間上維護其整體連續的假象,並提供隨機存取的接口。
實際上。deque內部會維護一個map作為主控(注意!不是STL中的map容器),即一小塊連續的空間,該空間中每個元素都是指針,指向另一段(較大的)區域,這個區域稱為緩沖區(deque的存儲主體),緩沖區用來保存deque中的數據。因此deque在隨機訪問和遍歷數據會比vector慢。它首次插入一個元素,默認會動態分配512字節空間,當這512字節空間用完后,它會再動態分配自己另外的512字節空間,然后虛擬地連在一起。deque的這種設計使得它具有比vector復雜得多的架構、算法和迭代器設計。它的隨機訪問和遍歷性能比vector差。
deque是一種優化了的對序列兩端元素進行添加和刪除操作的基本序列容器。通常由一些獨立的區塊組成,第一區塊朝某方向擴展,最后一個區塊朝另一方向擴展。它允許較為快速地隨機訪問但它不像vector一樣把所有對象保存在一個連續的內存塊,而是多個連續的內存塊。並且在一個映射結構中保存對這些塊以及順序的跟蹤。
deque沒有所謂的容量觀念,因為他是動態的一分段連續的空間組合而成,隨時可以增加一段新的空間並鏈接起來。
雖然deque也提供了隨機訪問迭代器(Ramdon Acces Iterator),但是它的迭代器並不是普通的指針,這當然會影響各個運算層面。因此,除非必要,我們盡可能地選擇vector而非deque.
在對deque進行排序操作的時候,為了提高效率先將deque中的元素完整地復制到vector中,然后再vector中進行排序,在復制回到deque中.
一.成員函數
構造函數與析構函數:
迭代器訪問操作函數
這里c代表常量const,r代表reverse逆操作.
值訪問操作和狀態判定操作
注意沒有提供容量操作capacity()。除了at(),沒有任何成員函數會檢查索引或迭代器是否有效。元素的插入或刪除可能導致內存重新分配,所以任何插入或刪除動作都會使所有指向deque元素的指針、引用和迭代器失效。惟一例外的是在頭部或尾部插入元素,操作之后,指針和引用仍然有效,但迭代器將失效。
值修改操作
注意,pos為迭代器類型。僅僅只有使用erase操作及刪除數據操作才會返回指向下一個數據的迭代器。push_back()或push_front()插入元素時發生異常,不會拋出異常。另外還包括賦值函數assign(),如下:
#include <iostream> #include <deque> int main () { std::deque<int> first; std::deque<int> second; std::deque<int> third; first.assign (7,100); // 7 ints with a value of 100 std::deque<int>::iterator it; it=first.begin()+1; second.assign (it,first.end()-1); // the 5 central values of first int myints[] = {1776,7,4}; third.assign (myints,myints+3); // assigning from array. std::cout << "Size of first: " << int (first.size()) << '\n'; std::cout << "Size of second: " << int (second.size()) << '\n'; std::cout << "Size of third: " << int (third.size()) << '\n'; return 0; }
代碼2:常見操作
#include <deque> #include <cstdio> #include <algorithm> using namespace std; int main() { deque<int> ideq(20); //Create a deque ideq with 20 elements of default value 0 deque<int>::iterator pos; int i; for (i = 0; i < 20; ++i) ideq[i] = i; printf("輸出deque中數據:\n"); for (i = 0; i < 20; ++i) printf("%d ", ideq[i]); putchar('\n'); //在頭尾加入新數據 printf("\n在頭尾加入新數據...\n"); ideq.push_back(100); ideq.push_front(i); //輸出deque printf("\n輸出deque中數據:\n"); for (pos = ideq.begin(); pos != ideq.end(); pos++) printf("%d ", *pos); putchar('\n'); //查找 const int FINDNUMBER = 19; printf("\n查找%d\n", FINDNUMBER); pos = find(ideq.begin(), ideq.end(), FINDNUMBER);//注意迭代器類型在此查找 if (pos != ideq.end()) printf("find %d success\n", *pos); else printf("find failed\n"); //在頭尾刪除數據 printf("\n在頭尾刪除數據...\n"); ideq.pop_back(); ideq.pop_front(); //輸出deque printf("\n輸出deque中數據:\n"); for (pos = ideq.begin(); pos != ideq.end(); pos++) printf("%d ", *pos); putchar('\n'); return 0; }
二.容器的選擇
1.強調快速隨機訪問。則vector要比list好得多 。
2.已知要存儲元素的個數。vector 好於list。
3.強調增刪且不要在兩端插入修改元素。則list顯然要比vector好。
4.除非我們需要在容器首部插入和刪除元素,deque好於vector。因為vector僅僅在尾部增刪快速。
6.如果只需要在讀取輸入時在容器的中間位置插入元素,然后需要隨機訪問元素,則可考慮輸入時將元素讀入到一個List容器,然后排序,然后將排序后的list容器復制到一個vector容器中。
5.如果只在容易的首部和尾部插入數據元素,則選擇deque.