STL容器適配器之stack、queue的實現

stack

stack是沒有迭代器的,而STL要求每一種容器都必須內置一個迭代器,因此stack不是一種容器。 棧是一種先進後出的數據結構,一個棧的插入、刪除或取值都只能在棧頂實現,在元素不彈出的前提下不能夠遍歷內部所有的元素。
根據棧的性質,棧頂元素必須是最後一個進入的元素,根據這點,我們可以很容易得出一個結論:任何提供末端插入push_back、刪除pop_back、訪問back都能夠被stack容器封裝與修飾, 封裝是指通過stack對象,不能直接訪問被封裝的底層容器,而修飾是指stack在對底層容器做封裝時還提供了必要的接口,以滿足用戶的需要。 我們將被適配器封裝的底層容器稱爲基礎容器

適配器能夠對原始事物進行一次封裝與修飾,並提供另一種接口,該接口能夠更好地滿足用戶的需求,具有一定的專一性。

在之前學過的順序容器中,只要能夠提供末端的插入、刪除和訪問操作,都可以作爲stack適配器的基礎容器,所以vectorlistdeque都可以作爲stack的基礎容器, stack默認的基礎容器是deque

對於stack,我們通常需要提供的接口函數如下:

  1. 獲取棧內當前元素的個數size_type size();
  2. 獲取棧頂元素T top();
  3. 入棧void push(const T &t);
  4. 出棧void pop();
  5. 判斷是否爲空棧bool empty();

如果想使用STL定義的容器適配器stack,需要引用stack頭文件#include<stack>

stack的源碼👇

  1. 底層是deque
#include<iostream>
#include<deque>
using namespace std;
  1. stack適配器的定義
template<class T,class Sequence=deque<T> >
class stack
{
	friend bool operator==(const stack&,const stack&);//friend函數是全局函數,不受private的限制
	friend bool operator<(const stack&,const stack&);//類內聲明,類外定義,定義是不加friend
	public:
		typedef typename Sequence::value_type value_type;//typename類型聲明,元素類型
		typedef typename Sequence::size_type size_type;//大小類型
		typedef typename Sequence::reference reference;//引用聲明
		typedef typename Sequence::const_reference const_reference;//常引用聲明
	protected:
		Sequence c;//內部維護的容器,默認deque
	public:
		bool empty()const;//是否爲空
		size_type size()const;//大小
		reference top();//取頂部元素
		const_reference top()const;
		void push(const value_type &x);//壓棧
		void pop();//出棧
};
  1. 各個函數接口的類外實現
template<class T,class Sequence>
bool operator==(const stack<T,Sequence> &x, const stack<T,Sequence> &y)//判斷兩個適配器是否相等
{
	return x.c==y.c;
}
 
template<class T,class Sequence>
bool operator<(const stack<T,Sequence>& x,const stack<T,Sequence>& y)//判斷適配器x是否小於適配器y
{
	return x.c<y.c;
}
template<class T,class Sequence>
bool stack<T,Sequence>::empty()const//常成員函數類外定義需要加const關鍵字
{
	return c.empty();
}
template<class T,class Sequence>//類外無需加默認形參
//如果寫成size_type stack<T,Sequence>::size()const是錯誤的,因爲size_type是在類內定義的,且typename最好也加上
typename stack<T,Sequence>::size_type stack<T,Sequence>::size()const
{
	return c.size();
}
template<class T,class Sequence>
typename stack<T,Sequence>::reference stack<T,Sequence>::top()//底層實現是返回最後一個容器的元素
{
	return c.back();
}
template<class T,class Sequence>
typename stack<T,Sequence>::const_reference stack<T,Sequence>::top()const//top函數的重載
{
	return c.pop_back();
}
template<class T,class Sequence>
void stack<T,Sequence>::push(const value_type & x)//底層實現是向基礎容器的尾部添加元素
{
	c.push_back(x);
}
template<class T,class Sequence>
void stack<T,Sequence>::pop()//底層實現是將基礎容器的尾部元素彈出
{
	c.pop_back();
}

queue

queue內部依舊沒有迭代器,能實現queue功能的容器都可以作爲底層容器以封裝修飾,本質上是適配器
隊列的特點是先進先出,從隊尾插入隊首彈出,因此需要有pop_front,所以vector容器不適合作爲底層容器,而是dequelist適合,默認是deque

queue所提供的操作如下:
(1)獲取當前隊列中元素的個數。size_type size()
(2)獲取隊首元素(不彈出)T & front()
(3)獲取隊尾部元素(不彈出)T & back()
(4)入隊操作 void push(const T &t)
(5)出隊操作 void pop()
(6)判斷隊列是否爲空 bool empty()
同樣用queue需要#include<queue>

實現源碼👇

  1. deque爲底層容器
#include<iostream>
#include<deque>
using namespace std;

  1. queue的定義
#include<iostream>
#include<deque>
using namespace std;
 
/****************queque的定義*************/
template<class T,class Sequence=deque<T> >
class queue
{
	friend bool operator==(const queue& x,const queue& y);
	friend bool operator<(const queue&x,const queue& y);
	/****************容器適配器queue公有屬性*********************/
	public:
		typedef typename Sequence::value_type value_type;//容器元素類型
		typedef typename Sequence::size_type  size_type;//大小類型
		typedef typename Sequence::reference  reference;//引用類型
		typedef  typename Sequence::const_reference const_reference;//常引用類型
	protected:
		Sequence c;//基礎容器
		/*************queue的常用操作****************/
	public:
		bool empty()const;//判斷是否爲空
		size_type size()const;//元素個數
		reference front();//獲取隊首元素
		const_reference front()const;
		reference back();//獲取隊尾元素
		const_reference back()const ;
		void push(const value_type& x);//進隊列
		void pop();//出隊操作
};
  1. queue類外實現
template<class T,class Seq>
bool queue<T,Seq>::empty()const//判斷隊列是否爲空隊列,const在類外實現的時候也不能省
{
	return c.empty(); 
}
 
template<class T,class Seq>
typename queue<T,Seq>::size_type queue<T,Seq>::size()const//返回隊列內元素的個數
{
	return c.size();
}
 
template<class T,class Seq>
typename queue<T,Seq>::reference queue<T,Seq>::front()//獲取隊首元素
{
	return c.front();
}
 
template<class T,class Seq>
typename queue<T,Seq>::const_reference queue<T,Seq>::front()const//返回隊首元素的常引用
{
	return c.front();
}
 
template<class T,class Seq>
typename queue<T,Seq>::reference queue<T,Seq>::back()//取隊尾元素的引用
{
	return c.back();
}
 
template<class T,class Seq>
typename queue<T,Seq>::const_reference queue<T,Seq>::back()const//取隊尾元素的引用
{
	return c.back();
}
 
template<class T,class Seq>
void queue<T,Seq>::push(const value_type& t)//壓隊列
{
	c.push_back(t);
}
 
template<class T,class Seq>
void queue<T,Seq>::pop()//出隊列
{
	c.pop_front();
}

  1. 測試代碼
int main()
{
	queue<int> q;
	q.push(1);
	q.push(2);
	q.push(3);
	q.push(4);
	while(!q.empty())
	{
		cout<<"size="<<q.size()<<" ";
		cout<<q.front()<<endl;
		q.pop();
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章