deque源碼1(deque概述、deque中的控制器) html
deque源碼2(deque迭代器、deque的數據結構)node
deque源碼3(deque的構造與內存、ctor、push_back、push_front)算法
deque源碼4(deque元素操做:pop_back、pop_front、clear、erase、insert)數據結構
deque的迭代器dom
deque是分段連續空間,維持其"總體連續"的假象任務,落在了迭代器的operator++和operator--兩個運算子身上。post
對於operator:一、必須可以指出分段連續空間(即緩衝區)在哪裏this
二、必須可以判斷本身是否已經處於其所在緩衝區的邊緣,在跳躍時,必須掌握控制中心。spa
以下圖:3d
template <class T,class Ref,class Ptr,size_t Bufsize> struct __deque_iterator{ //爲繼承 std::iterator typedef __deque_iterator<T,T&,T*,Bufsize> iterator; typedef __deque_iterator<T,const T&,const T*,Bufsize> const_iterator; static size_t buffer_size(){return __deque_buf_size(Bufsize,sizeof(T));} //未繼承std::iterator,因此必須自行撰寫五個必要的迭代器相應型別 typedef random_access_iterator_tag iterator_category; //1 typedef T value_type; //2 typedef Ptr pointer; //3 typedef Ref renference; //4 typedef size_t size_type; typedef ptrdiff_t difference_type; //5 typedef T** map_pointer; typedef __deque_iterator self; //保持與容器的聯結 T* cur; //此迭代器所指之緩衝區中的現行(current)元素 T* first; //此迭代器所指之緩衝區中的頭 T* last; //此迭代器所指之緩衝區中的尾(含備用空間) map_pointer node; //指向管控中心 ... inline size_t __deque_buf_size(size_t n,size_t sz){ return n!=0? n:(sz<512? size_t(512/sz):size_t(1)); } /* n!=0,返回n,表示buffer_size由用戶自定義 n=0,表示buffer_size使用默認值,那麼: sz<512,傳回512/sz; sz>=512,傳回1 */ };
例如:產生一個deque<int>,令緩衝區大小爲32,因而每一個緩衝區能夠容納32/sizeof(int)=8個元素,通過增刪操做,deque中包含20個元素,deque狀況以下圖:指針
start和finish分別指向deque的第一個緩衝區和最後一個緩衝區,20/8=3,因此map擁有3個節點,且最後一個緩衝區還有插入元素的空間。
用於迭代器內對各類指針運算都進行重載操做,因此各類運算算法都比較麻煩,特別是對於在緩衝區邊緣的元素操做都須要調用set_node操做,來跳一個緩衝區。代碼以下:
void set_node(map_pointer new_node){ node=new_node; first=*new_node; last=first+difference_type(buffer_size()); }
重載運算符以下:
renference operator*() const {return *cur;} pointer operator->() const {return &(operator*());} difference_type operator-(const self& x)const{ return difference_type(buffer_size())*(node-x.node-1)+(cur-first)+(x.last-x.cur); } self& operator++(){ ++cur; //切換下一個元素 if(cur==last){ //若是已達到所在緩衝區的尾端 set_node(node+1); //利用set_node方法切換到下一個緩衝區 cur=first; } return *this; } self operator++(int){ self temp=*this; ++*this; //調用operator++ return temp; } self& operator--(){ if(cur==first){ //若是達到緩衝區的頭部 set_node(node-1); //利用set_node方法切換到上一個緩衝區 cur=first; } --cur; return *this; } self operator--(int){ self temp=*this; --*this; //調用operator-- return temp; } self& operator+=(difference_type n){ //實現隨機存取、迭代器能夠直接跳躍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{ self temp=*this; return temp+=n; //調用operator+= } self& operator-=(difference_type n){ return *this+=-n; } self operator-(difference_type n) const{ self temp=*this; return temp-=n; //調用operator-= } //隨機存取第n個元素 reference operator[](difference_type n)const {return *(*this+n);} bool operator==(const self& x)const{return cur==x.cur;} bool operator!=(const self& x)const{return !(*this==x);} bool operator<(const self& x)const{ return (node==x.node)?(cur<x.cur):(node<x.node); }
deque的數據結構
deque除了維護上文map的指針外,還要維護start,finish兩個迭代器(上圖2可見),分別指向第一個緩衝區的第一個元素和最後一個緩衝區的最後一個元素的下一個位置(可能還有備用空間),此外,它固然也必須記住目前的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: typedef pointer* map_pointer;//元素的指針的指針 protected: iterator start; //表示第一個節點 iterator finish; //表示最後一個節點 map_pointer map; //指向map,map是塊連續空間,其每一個元素都是指針,指向一個節點 size_type map_size; //map內有多個指針 ... public: iterator begin(){return start;} iterator end(){return finish;} reference operator[](size_type n){ return start[difference_type(n)]; //調用operator[] } reference front(){return *start;} //調用operator* reference back(){ iterator temp=finish; --temp; //調用operator-- return *temp; //調用operator* } size_type size() const{return finish-start;} //調用operator- size_type max_size() const{return size_type(-1);} bool empty() const{return finish==start;} };