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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值