STL序列式容器之deque
一、概述
deque是一種雙向開口的連續線性空間,所謂雙向是指可以在首尾兩端進行插入和刪除,邏輯結構如圖所示:
deque和vector最大的差異在於deque可以在常數時間內對頭端進行插入和刪除操作,而且deque沒有容量的概念,隨時可以增加一段新的空間並連結起來。除非必要,應儘量使用vector而非deque。對deque進行排序操作為了提高效率可以先將deque複製到vector中,將vector排序後(利用STL sort演算法)再複製回deque。
二、deque內部結構
deque由一段一段的定量連續空間構成,一旦有必要在deque的前端或者尾端增加新空間,便配置一定的連續空間,串接在整個deque的頭端或者尾端,deque最大的任務便是維護這些連續空間整體連續的假象,並提供隨機存取的介面
deque的迭代器應該能夠指出分段連續空間在哪裡,必須能夠判斷自己是否處在其所在緩衝區的邊緣,如果是則應能夠跳到下一個或上一個緩衝區上。其中控器、迭代器和緩衝區的關係如下圖。迭代器內的cur指標指向當前緩衝區的當前元素,first指向首元素,last指向尾元素,node回指此緩衝區迭代器在中控器中的位置。
對於一個存放了23個元素的deque再加入一個元素,其結構圖如下。start迭代器內含第一個緩衝區指標資訊,finish迭代器內含最後一個緩衝區資訊。deque::begin()傳回迭代器start,deque::end()傳回迭代器finish。
正因為deque內部的結構複雜,所以存取元素時deque的內部多一個間接過程,相比於vector會慢一點。deque迭代器需要在不同區塊之間跳轉,所以必須是智慧型指標。deque的迭代器屬於隨機存取迭代器。
三、deque的核心介面
在標頭檔案<deque>中,class deque定義如下:
namespace std {
template <class T,
class Allocator = allocator<T> >
class deque;
}
第一個引數代表元素型別,帶有預設值的第二個引數定義deque記憶體模型,預設使用allocator。
1. 構造和解構函式
操作 | 效果 |
---|---|
deque<Elem> c | 產生一個存放Elem型別元素的空deque |
deque<Elem> c1(c2) | 針對某個deque產生一個同型副本 |
deque<Elem> c(n) | 產生一個含有n個元素,以default建構函式產生元素的deque |
deque<Elem> c(n,elem) | 產生一個含有n個elem元素deque |
deque<Elem> c(beg,end) | 產生一個以區間[beg,end]內元素為初值的deque |
c.~deque<Elem>() | 銷燬所有元素,釋放記憶體 |
2. 非變動性操作
操作 | 效果 |
---|---|
c.size() | 返回實際容器的大小。 |
c.empty() | 判斷容器大小是否為0。 |
c.max_size() | 返回可容納元素最大數量 |
c1 == c2 | 判斷c1是否等於c2 |
c1 != c2 | 判斷c1是否不等於c2 |
c1 < c2 | 判斷c1是否小於c2 |
c1 > c2 | 判斷c1是否大於c2 |
c1 <= c2 | 判斷c1是否小於等於c2 |
c1 >= c2 | 判斷c1是否大於等於c2 |
c.at(idx) | 返回索引位置idx處的元素,如果idx越界,丟擲out_of_range異常 |
c[idx] | 返回索引位置idx處的元素,不進行範圍檢查 |
c.front() | 返回第一個元素,不檢查元素是否存在 |
c.back() | 返回最後一個元素,不檢查元素是否存在 |
c.begin() | 返回一個隨機存取迭代器,指向第一元素 |
c.end() | 返回一個隨機存取迭代器,指向最後一個元素的下一位置 |
c.rbegin() | 返回一個逆向迭代器,指向逆向迭代時的第一個元素 |
c.rend() | 返回一個逆向迭代器,指向逆向迭代時最後元素的下一位置 |
3. 變動性操作
操作 | 效果 |
---|---|
c1 = c2 | 將c2的所有元素賦值給c1 |
c.assign(n,elem) | 將n個elem副本賦值給c |
c.assign(beg,end) | 將區間[beg,end]中的元素賦值給c |
c1.swap(c2) | 將c1和c2中的元素互換 |
swap(c1,c2) | 同上,此為全域性函式 |
c.insert(pos,elem) | 在pos位置插入一個elem副本,返回新元素的位置 |
c.insert(pos,n,elem) | 在pos位置插入n個elem副本,無返回值 |
c.insert(pos,beg,end) | 在pos位置插入區間[beg,end]內的元素,無返回值 |
c.push_back(elem) | 在尾部新增一個elem的副本 |
c.pop_back() | 移除最後一個元素,不回傳 |
c.push_front(elem) | 在頭部插入一個elem副本 |
c.pop_front() | 移除頭部元素,不回傳 |
c.erase(pos) | 移除pos位置上的元素,返回下一元素的位置 |
c.erase(beg,end) | 移除區間[beg,end]內的元素,返回下一元素的位置 |
c.resize(num) | 將大小改為num。如果size增長了,新增大小以default建構函式產生出來 |
c.resize(num,elem) | 將大小改為num。如果size增長了,新增大小以elem副本產生出來 |
c.clear() | 移除所有元素,將容器清空 |
三、程式示例
deque的使用示例
//example of deque
#include <iostream>
#include <deque>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
deque<string> coll;
coll.assign(3, string("string"));
coll.push_back("last string");
coll.push_front("first string");
copy(coll.begin(), coll.end(),
ostream_iterator<string>(cout, "\n"));
cout << endl;
coll.pop_front();
coll.pop_back();
copy(coll.begin(), coll.end(),
ostream_iterator<string>(cout, "\n"));
for (unsigned int i = 1; i < coll.size(); ++i){
coll[i] = "another " + coll[i];
}
cout << endl;
coll.resize(4, "resized string");
copy(coll.begin(), coll.end(),
ostream_iterator<string>(cout, "\n"));
return 0;
}
輸出結果: