C++stack与queue模拟实现
Posted xiao zhou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++stack与queue模拟实现相关的知识,希望对你有一定的参考价值。
前言
xxxx无论是当初在学校最先学习C语言版的数据结构,还是现在学习STL,发现大家(包括我)都喜欢将stack(栈)和queue(队列)放在一起。可能是FILO和FIFO两种数据存储方式过于相近,更能深入人心,因此两者经常会被放在一起。但是STL我把他们放在一起更是有原因。因为这两种容器在模拟实现的时候,都会使用到“适配器”。这个在后面我再具体说明。
stack栈
xxxx栈的基本知识相信大家都已经了解,在此我就不再赘述。栈的逻辑结构如图
现在我们就要用C++进行实现。我们当初用C语言实现栈的时候,最多的情况都是使用的数组来模拟栈。数组的头代表数组的栈底;数组的尾代表栈顶。由于栈对数据的push、pop都是在栈顶操作,所以使用数组就能在时间复杂度为O(1)的情况下完成操作,十分高效。
xxxx这里有一个很重要的事情,就是C语言中,我们用数组来模拟栈。那C++呢??数组的结构特点非常适合来作为栈,所以我们能否仍然使用数组(vector)来作为栈的基础数据结构从而实现栈呢?
xxxx答案是肯定的,我们仍然需要使用数组(不是说只能使用数组,只不过数组更普遍,并且STL中的stack就是使用vector来实现的)但是我们知道,栈还有链栈,或者某些特殊要求我们不能使用vector,而是其他的容器更适合当前的操作情况。这时候,为了代码的通用性,避免代码冗余,为了面对不同的需要,我们不用每次都要写一份逻辑相同而使用的容器不同的stack,我们就要引入**“适配器”**的概念。
适配器
提前声明:我在这里讲的适配器,只是适配器的一小部分,对于模拟实现stack和queue所需要的部分。
xxxx什么是适配器?大家现实生活中应该都有许多类型的适配器。比如:家用220V电压是从高压输电线通过电压转变过来的、两孔三孔插头之间转化……功能类似于下图这种。
xxxx简单来说,就是一种转变。而在这里是什么的转变呢?答案是:容器的转变。
xxxx现在我们的目的是使用各种转变成stack。我们就需要模板。类模板详解请点这里。下面我们直接看一下如何使用模板成为适配器。
template<class T, class Container = vector<T>>
class stack
{
private:
Container _con;
};
以上就是它的基本格式。我们最简单的理解就是,我们将vector进行一次封装。通过成员函数对他的行为进行约束,让他变成具有stack属性的一种新容器,这种容器我们成为stack。
注:STL中使用的是deque,我们使用vector影响不大,使用vector与C语言有很好的联系,方便理解,否则有些同学刚学到这里,还不知道deque是什么,会影响学习
stack的成员函数
namespace zzk
{
template<class T, class Container = std::deque<T>>
class stack
{
public:
//默认成员函数都不用写,就直接使用deque的就行
void push(const T x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_back();
}
T top() const
{
return _con.back();
}
size_t size() const
{
return _con.size();
}
bool empty() const
{
return _con.empty();
}
private:
Container _con;
};
}
xxxx我们可以很容易发现,完全就是对vector成员函数进行一次封装,因为操作逻辑完全一样,所以只需要对vector的行为封装成stack即可完成。
queue队列
xxxx我们在C语言中的队列可以用链表或者数组。
在C++中,我们仍然要使用适配器这种方式,对某种容器进行封装,形成队列。由于vector不支持头删,所以我们要使用deque或者链表。STL中默认使用的是deque。
经过stack的学习,queue应该比较容易理解,我们直接上代码!!
queue类
namespace zzk
{
template<class T, class Container = std::deque<int>>
class queue
{
public:
void push(const T& x)
{
_con.push_back(x);
}
void pop()
{
_con.pop_front();
}
T front()
{
return _con.front();
}
bool empty()
{
return _con.empty();
}
size_t size()
{
return _con.size();
}
private:
Container _con;
};
}
xxxx还是对已有容器的封装,由于逻辑类似,因此我们直接复用原容器的接口即可。
总结
xxxx栈和队列都使用了“适配器”,在这里,适配器的作用就是对现有容器的一种封装,由于操作逻辑相同,因此只需要对接口进行一次封装即可。对于逻辑不相同的。如用vector实现优先队列priority_queue,由于逻辑不相同,就需要加以其他代码,使符合priority_queue的功能特点。
以上是关于C++stack与queue模拟实现的主要内容,如果未能解决你的问题,请参考以下文章
C++STL-stack与queue以及priority_queue
C++初阶第十二篇—stack和queue(stack和queue的常见接口的用法与介绍+priority_queue+容器适配器+仿函数+模拟实现)