deque是一種雙向開口的連續線性空間,能夠在頭尾兩端分別作元素插入和刪除操做。deque沒有「容量」(capacity)的觀念,是動態地以分段連續空間組合而成,隨時能夠增長一段新空間如何鏈接起來。前端
deque是由一段段的定量連續空間組成。一旦須要在deque的前端或者尾端增長新空間,便配置一段定量連續空間,串接在整個deque的頭端或者尾端。node
deque採用一塊所謂的map(不是stl的map容器)做爲主控。這裏的map是一塊連續空間,其中每一個元素都是一個指針,指向另外一段較大的線性連續空間,這段空間稱爲緩衝區。緩衝區是deque存儲空間的主體。sgi stl容許指定緩衝區的大小,默認值0表示使用512bytes緩衝區。數據結構
template <class T,class Alloc=alloc,size_t BufSiz=0> class deque{ public: typedef T value_type; typedef value_type* pointer; ... protected: typedef pointer* map_pointer; protected: map_pointer map; //指向map,map是連續空間,其內的每一個元素都是一個指針,指向一塊緩衝區 size_type map_size; //map可容納多少指針 ... };
map是一個指向指針的指針,指向型別爲T的一塊空間dom
deque是分段的連續空間,維持其總體連續假象的任務,落在了迭代器身上。它應該具備如下結構:
一、指出緩衝區的位置。this
二、判斷是否處於緩衝區邊緣,若是是,一旦前進或者後退必須可以跳躍到下一個或上一個緩衝區。spa
template <class T, class Ref, class Ptr, size_t BufSiz> struct __deque_iterator { // 基本型別的定義 typedef __deque_iterator<T, T&, T*, BufSiz> iterator; typedef random_access_iterator_tag iterator_category; typedef T value_type; typedef Ptr pointer; typedef Ref reference; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T** map_pointer; typedef __deque_iterator self; // 緩衝區的大小 tatic size_t buffer_size() { ... } // 保持與容器的鏈接 T* cur; // 指向當前緩衝區的現行元素 T* first; // 指向當前緩衝區的頭 T* last; // 指向當前緩衝區的尾 map_pointer node; // 指向管控重心map // ... };
下面是map對幾個關鍵行爲的操做步驟。3d
//用於跳轉緩衝區 void set_node(map_pointer new_node) { node = new_node; first = *new_node; last = first + difference_type(buffer_size()); } // 迭代器之間的距離(相隔多少個元素) difference_type operator-(const self& x) const { return difference_type(buffer_size()) * (node - x.node - 1) + (cur - first) + (x.last - x.cur); } reference operator*() const { return *cur; } pointer operator->() const { return &(operator*()); } self& operator++() { ++cur; if (cur == last) { // 到達緩衝區尾端 set_node(node + 1); cur = first; } return *this; } self& operator++(int){ self tmp = *this; ++*this; return tmp; } self& operator--() { if (cur == first) { // 已到達緩衝區頭端 set_node(node - 1); cur = last; } --cur; return *this; } self& operator--(int){ self tmp = *this; --*this; return tmp; } self& operator+=(difference_type n) {//支持ite+=n difference_type offset = n + (cur - first); if (offset >= 0 && offset < difference_type(buffer_size())) cur += n;//若是還在當前節點,直接加 else {//不然跳到下個節點 difference_type node_offset = offset > 0 ? offset / difference_type(buffer_size()) : -difference_type((-offset - 1) / buffer_size()) - 1; set_node(node + node_offset); cur = first + (offset - node_offset * difference_type(buffer_size())); } return *this;//返回當前對象引用 } self operator+(difference_type n) const {//重載const重載+號。 self tmp = *this; return tmp += n; } self& operator-=(difference_type n) { return *this += -n; }//ite -=n經過+ -n實現。 self operator-(difference_type n) const {//重載- self tmp = *this; return tmp -= n; } //實現隨機存儲,迭代器調用operator* 和 operator+ reference operator[](difference_type n) const { return *(*this + n); }//重載ite[]操做,經過+實現 bool operator==(const self& x) const { return cur == x.cur; }//重載ite1 == ite2 bool operator!=(const self& x) const { return !(*this == x); }//重載ite1 != ite2 bool operator<(const self& x) const { return (node == x.node) ? (cur < x.cur) : (node < x.node); }
deque除了維護一個指向map的指針,也維護start和finish兩個迭代器,分別指向第一緩衝區的第一個元素和最後一個緩衝區最後一個元素的下一個位置。此外它也須要記住map的大小,一旦map提供的節點不足,急須要從新配置一塊更大的map指針
template<class T, class Alloc = alloc, size_t BufSiz = 0> class deque{ public : typedef T value_type ; typedef value_type* pointer ; typedef size_t size_type ; public : typedef __deque_iterator<T,T&,T*,BufSiz> iterator ; protected : //元素的指針的指針(pointer of pointer of T) typedef pointer* map_pointer ; protected: iterator start ; //表現第一節點 iterator finish ; //表現最後一個節點 map_pointer map ; //指向map,map是塊連續空間,其每一個元素都是個指針,指向一個節點(緩衝區) size_type map_size ; //map內有多少指針 ... } ;
關於deque的內存構造與管理的篇幅過於長,細節也較多,博客篇幅太小是在不宜細寫。建議閱讀原書籍章節理解code