两个队列实现一个栈
1.题目描述
使用两个队列来实现一个栈
2.队列与栈
- 栈(stack)又称为栈或堆叠,是计算机科学中一种特殊的串列形式的抽象数据类型,其特殊之处在于只能允许在链表或数组的一端(称为堆栈顶端指针,top)进行加入数据(push)和输出数据(pop)的运算。由于堆栈数据结构只允许在一端进行操作,因而按照后进先出(LIFO, Last In First Out)的原理运作。
-
empty() 是否为空
size() 返回大小
top 返回栈顶数据
push() 栈顶压入一个数据
pop() 抛弃栈顶数据 - 队列(queue),是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(rear)进行插入操作,在前端(front)进行删除操作。队列的操作方式和堆栈类似,唯一的区别在于队列只允许新数据在后端进行添加。
empty() 是否为空
size() 返回大小
front() 返回队头数据
back() 返回队尾数据
push() 队尾压入一个数据
pop() 抛弃队头数据
- 在STL中,栈和队列其实都是通过双向队列来实现的,简单的限制插入和删除的方向。
template<typename _Tp, typename _Sequence = deque<_Tp> >
class stack
{
...
}
template<typename _Tp, typename _Sequence = deque<_Tp> >
class queue
{
...
}
3.实现push函数
template<typename T>
void CStack<T>::push(const T& value)
{
if(queue1.size() >=queue2.size()){
queue1.push(value);
}else{
queue2.push(value);
}
}
通过上面代码,我们可以看出,我们是在size()更大的队列中插入数据。那么有一个队列就始终是空的,空的队列是为了我们删除元素的时候做为辅助队列。
4.pop()实现
template<typename T>
T CStack<T>::pop()
{
if(queue1.empty()&&queue2.empty())
throw logic_error("stack is empty");
if(!queue2.empty())
{
while(queue2.size() >1)
{
//queue2中元素压出到queue1中
T& value = queue2.front();
queue2.pop();
queue1.push(value);
}
T value = queue2.front();
queue2.pop();
return value;
}else{
while(queue1.size() >1)
{
//queue1中元素压出到queue2中
T& value = queue1.front();
queue1.pop();
queue2.push(value);
}
T value = queue1.front();
queue1.pop();
return value;
}
}
通过上面代码我们可以看出,如果两个队列都是空的,即size()是0,那么进行pop的时候,抛出异常。之后,如果a队列不为空,那么b队列做辅助队列。在a队列还剩一个元素的时候,把a队列的元素压出,放到b队列里面,则a队列中唯一的一个元素就是我们要删除的元素,同时返回此元素。当b队列不为空,同上。
5.完整代码
stack.h
#ifndef STACK_H
#define STACK_H
#include <queue>
#include <stdexcept>
#include <iostream>
#include <deque>
using namespace std;
template<typename T>
class CStack
{
public:
CStack();
~CStack();
void push(const T& value);
T pop();
private:
queue<T> queue1;
queue<T> queue2;
};
template<typename T>
CStack<T>::CStack()
{
}
template<typename T>
CStack<T>::~CStack()
{
}
template<typename T>
void CStack<T>::push(const T& value)
{
if(queue1.size() >=queue2.size()){
queue1.push(value);
}else{
queue2.push(value);
}
}
template<typename T>
T CStack<T>::pop()
{
if(queue1.empty()&&queue2.empty())
throw logic_error("stack is empty");
if(!queue2.empty())
{
while(queue2.size() >1)
{
//queue2中元素压出到queue1中
T& value = queue2.front();
queue2.pop();
queue1.push(value);
}
T value = queue2.front();
queue2.pop();
return value;
}else{
while(queue1.size() >1)
{
//queue1中元素压出到queue2中
T& value = queue1.front();
queue1.pop();
queue2.push(value);
}
T value = queue1.front();
queue1.pop();
return value;
}
}
#endif // STACK_H
main.cpp
#include <iostream>
#include "stack.h"
using std::cout;
using std::endl;
int main(){
try{
CStack<char> stack;
stack.push('a');
stack.push('b');
stack.push('c');
char head = stack.pop();
cout <<head;
stack.push('d');
head = stack.pop();
cout<<head;
stack.push('e');
head = stack.pop();
cout<<head;
head = stack.pop();
cout<<head;
head = stack.pop();
cout<<head;
head = stack.pop();
cout<<head;
head = stack.pop();
cout<<head;
head = stack.pop();
cout<<head;
}
catch(exception& ex)
{
cout<<"\n"<<ex.what()<<endl;
}
return 0;
}
运行结果图: