stack
stack是沒有迭代器的,而STL要求每一種容器都必須內置一個迭代器,因此stack不是一種容器。 棧是一種先進後出的數據結構,一個棧的插入、刪除或取值都只能在棧頂實現,在元素不彈出的前提下不能夠遍歷內部所有的元素。
根據棧的性質,棧頂元素必須是最後一個進入的元素,根據這點,我們可以很容易得出一個結論:任何提供末端插入push_back
、刪除pop_back
、訪問back
都能夠被stack容器封裝與修飾, 封裝是指通過stack對象,不能直接訪問被封裝的底層容器,而修飾是指stack在對底層容器做封裝時還提供了必要的接口,以滿足用戶的需要。 我們將被適配器封裝的底層容器稱爲基礎容器
適配器能夠對原始事物進行一次封裝與修飾,並提供另一種接口,該接口能夠更好地滿足用戶的需求,具有一定的專一性。
在之前學過的順序容器中,只要能夠提供末端的插入、刪除和訪問操作,都可以作爲stack適配器的基礎容器,所以vector
、list
、deque
都可以作爲stack的基礎容器, stack默認的基礎容器是deque
、
對於stack,我們通常需要提供的接口函數如下:
- 獲取棧內當前元素的個數
size_type size();
- 獲取棧頂元素
T top();
- 入棧
void push(const T &t);
- 出棧
void pop();
- 判斷是否爲空棧
bool empty();
如果想使用STL定義的容器適配器stack,需要引用stack頭文件#include<stack>
stack的源碼👇
- 底層是deque
#include<iostream>
#include<deque>
using namespace std;
- 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();//出棧
};
- 各個函數接口的類外實現
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
容器不適合作爲底層容器,而是deque
、list
適合,默認是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>
實現源碼👇
- deque爲底層容器
#include<iostream>
#include<deque>
using namespace std;
- 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();//出隊操作
};
- 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();
}
- 測試代碼
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;
}