用栈来实现队列。
栈的特征是 先进后出;
队列的特征是 先进先出;
我们把1、2、3入栈A,然后出栈,把出栈元素入到另一个栈B中(即把3、2、1入到另一个栈中),这时操作栈B执行出栈操作,出栈的顺序是1、2、3.如此一折腾,使用两个栈,便把1、2、3按照先进先出的规则输出了。
就好比有个黑匣子,它使得进去的元素只能按照先后顺序出来:
使用两个栈来实现队列,有个需要考虑的问题是队列大小。假设所有元素都先执行入队操作(我们在黑匣子里,实际上是把它们都入了栈A中),待我们想要出队时,要把栈A的元素都倒入栈B中,在栈B中执行出栈操作即可。这就要求栈B的容量和栈A的容量至少一样大。我们发现栈A一旦满了,就没法往栈A中加元素了,即使栈B是空着的,也就是说队列的容量和栈A的容量一样大(当然你也可以把栈A的容量设置的非常大,而规定队列的容量很小,但这样就浪费了很多空间,没有必要)。
下面给出代码:
#include "Stack.h"
template <typename DataType> class QueueWithStacks
{
public:
QueueWithStacks(int capacity = 10)
{
_capacity = capacity;
_stack1 = new Stack<DataType>(capacity);
_stack2 = new Stack<DataType>(capacity);
}
~QueueWithStacks()
{
_stack1->~Stack();
_stack2->~Stack();
}
bool addDataToQueue(DataType data)
{
//如果栈2是空的,我们只需要向栈1中push
if (_stack2->isEmpty())
{
//如果此时栈1满了,返回false
return _stack1->push(data);
}else{//如果栈2中有元素,则要判断栈1中的元素加上栈2中的元素是否达到队列的容量
if(_stack1->count() + _stack2->count() < _capacity)
{
return _stack1->push(data);
}else{//队列满了,不能再入队列
return false;
}
}
}
DataType deleteDataFromQueue()
{
if (_stack2->isEmpty())//如果栈2是空的,要把栈1中的元素倒入栈2
{
//把栈1中的元素倒入栈2
while(!_stack1->isEmpty())
{
_stack2->push(_stack1->pop());
}
}
return _stack2->pop();
}
private:
Stack<DataType> * _stack1;//用来执行入队列
Stack<DataType> * _stack2;//用来执行出队列
int _capacity;//队列的容量
};
栈的代码是:
template<typename DataType> class Stack
{
public:
Stack(int capacity = 10)
{
_top = -1;
_capacity = capacity;
_datas = new DataType[capacity];
}
~Stack()
{
delete [] _datas;
}
bool push(DataType data)
{
//如果栈满了,返回false
if (_top + 1 == _capacity )return false;
_top++;
_datas[_top]=data;
return true;
}
DataType pop()
{
//如果栈为空,不能进行出栈操作,则退出
if (_top == -1)exit(1);
return _datas[_top--];
}
bool isEmpty(){
if (_top == -1)return true;
return false;
}
bool isFull(){
if (_top + 1 == _capacity)return true;
return false;
}
int count(){
return _top+1;
}
private:
DataType* _datas;
int _capacity;//栈的容量
int _top;//标志栈顶
};