[STL]deque和stack、queue


      怎么說呢,deque是一種雙向開口的連續線性空間,至少邏輯上看上去是這樣。然而事實上卻沒有那么簡單,准確來說deque其實是一種分段連續空間,因此其實現以及各種操作比vector復雜的多。

 

一.deque的中控器

      deque是有一段一段的定量連續空間構成,采用一塊所謂的map(當然不是map容器)作為主控。map是一小塊連續空間,其中每一個元素都是一個指針,指向另一段連續性空間(緩沖區)。緩沖區才是deque的儲存空間主體。我們可以指定緩沖區大小,默認值0表示使用512字節緩沖區。deque設計結構如下圖所示:

 

二.deque的數據結構

      deque除了維護map的指針外,也要維護startfinish兩個迭代器,分別指向第一緩沖區的第一個元素和最后緩沖區的最后一個元素(的下一個位置)。此外,它還要記錄當前map的大小,因為當map結點不夠的時候,需要另外配置一個更大的map,計算其大小需要知道當前map的大小(源碼為:new_map_size=map_size+max(map_size,nodes_to_add)+2;)。deque數據結構如下:

class deque
{
public:
	typedef T value_type;
	typedef valude_type *pointer;
	typedef size_f size_type;
public: //迭代器
	typedef __deque_iterator<T,T&,T*,BufSiz> iterator;
protected: //元素的指針的指針
	typedef pointer *map_pointer;
protected: 
	iterator start; 
	iterator finish;
	map_pointer map;
	size_type map_size; //map中指針個數
...
};

 

三.deque的成員函數

      考慮到deque的特殊結構,所以實現deque的各種操作都相當瑣碎復雜。最關鍵的就是判斷是否已經處於緩沖區邊緣,如果是,一旦前進或后退就必須跳躍至下一個或上一個緩沖區。還有一個重要問題就是當map前端或尾端備用空間不足時就要重新配置新map(配置更大的,拷貝原來的,釋放原來的),下面的push_back()和push_front()等函數都需要先判斷。下面分別解釋deque的各個成員函數。

  • push_back():當最后緩沖區有兩個(含)以上的空間,直接在緩沖區增加新元素;當最后緩沖區只剩一個備用空間時,push_back()調用push_back_aux(),先配置一個新的緩沖區,然后再在那個僅剩的備用空間定義新元素,並更改finish的狀態,令其指向新結點。
  • push_front():當第一緩沖區有備用空間時,直接在備用空間增加新元素;當第一緩沖區無備用空間時,調用push_front_aux()配置新結點(緩沖區),增加新元素,並改變start狀態。
  • pop_back():當最后緩沖區有一個(含)以上元素,就將finish向前移一位並將最后那個元素析構掉;當最后緩沖區沒有任何元素,就調用push_pop_aux()將這個緩沖區釋放。解釋一下:第一種情況finish指向最后緩沖區的first位置,第二種情況finish指向最后第二個緩沖區的last位置。
  • pop_front():第一緩沖區有兩個(含)以上元素,將第一個元素析構,將start后移;否則,將這個緩沖區釋放,start指向下一個緩沖區第一個元素。
  • clear():deque的最初狀態(即無任何元素時)保有一個緩沖區,因此clear()之后也一樣要保留一個緩沖區,finish=start。
  • erase():先判斷清除空間前后元素個數,移動較少一端
  • insert():若在最前端,即push_front(),最后端類似;判斷插入點前后元素個數,移動較少的一端

 

四.配接器stack和queue

      stack是一種先進后出(FILO)的數據結構,它只有一個出口。deque是雙向開口的數據結構,所以SGI STL便以deque作為缺省情況下的stack底部結構,封閉其頭端開口。stack沒有迭代器,所以除了頂部元素,無法存取其它元素,即不能遍歷stack。

      stack的成員函數都是針對其頂部元素進行操作:push(),pop(),top()。

      queue是一種先進先出(FIFO)的數據結構,它有兩個出口。queue也是以deque作為底部結構,封閉其底端的出口和前端的入口。queue,只有頂端(兩端)的元素能被外部使用,所以queue也沒有迭代器,不提供遍歷功能。

      queue的成員函數有:front(),back(),push(),pop()。

      可以看到stack和queue的成員函數以及特性都是針對其數據結構來的,所以深入理解其內部結構,不易與deque眾多的成員函數混淆。當然stack和queue也可以list為底層結構實現。

 

參考:《STL源碼剖析》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM