使用两个队列实现一个栈

时间:2022-08-30 17:39:18

  首先,我们得了解队列和栈的基本原理。

  队列是一个“先进先出“的一个结构。队列的定义是在队尾插入,在队头删除,这就要求要用一种在尾部插入容易的,在头部删除容易的结构,你一定会想到单链表,对,库的实现就是用一个链表实现的。

  栈,相信大家都不会陌生,函数栈帧等的实现,它是一种”先进后出“的结构。栈的插入删除都是在尾部进行的。

  所以要用队列实现一个栈,要解决的问题就是在删除时要删除最后插入的那个元素。

  我们先来模拟一下出栈和入栈的情况:

 (1)入栈:Q1:1,2,3,4入队列(相当于入栈);

 (2)出栈:Q1:1,2,3出队列,Q2:1,2,3入队列;(此时Q1只剩4,正是我们要出栈的元素)

 (3)

     1>入栈:Q1:5入队列(每次入栈都用Q1入队列实现,而不入队列Q2,这样会提高效率,后面会说到)

     2>出栈:判断:如果Q1队列不为空就用(1)(2)步的方法出栈最后一个元素。否则,出栈Q2队列的最后一个元素。

 我们首先来搭建这个栈的结构:

#pragma once
#include<iostream>
#include<queue>
#include<string>
#include<assert.h>

using namespace std;

template<class T>
class MYStack
{
public:
MYStack()
:_size(0)
{
}
~MYStack()
{
}
void Push(const T& x);
void Pop();
bool Empty();
size_t Size();
void Print();


private:
queue<T> q1;
queue<T> q2;
size_t _size;
};

  一个栈具有的功能我们都实现一下,Psh(),Pop(),Empty(),Size()等等。

  在这个结构中数据成员是两个队列的对象,因为我们是用两个队列来实现的,还有一个_size用来记录栈中元素的个数。

下面是函数具体实现:

template<class T>void MYStack<T>::Push(const T& x){q1.push(x);++_size;}template<class T>void MYStack<T>::Pop(){//assert(_size > 0);//size_t plen = q1.size();//while (plen != 1)//{//T tmp = q1.front();//q2.push(tmp);//q1.pop();//--plen;//}//q1.pop();//plen = q2.size();//while (plen)//{//T tmp = q2.front();//q1.push(tmp);//q2.pop();//--plen;//}//--_size;assert(_size > 0);size_t plen = q1.size();if (plen == 0){//if (q2.size() == 0)//return;plen = q2.size();while (plen != 1){T tmp = q2.front();q1.push(tmp);q2.pop();--plen;}q2.pop();}else{size_t plen = q1.size();while (plen != 1){T tmp = q1.front();q2.push(tmp);q1.pop();--plen;}q1.pop();}--_size;}template<class T>bool MYStack<T>::Empty(){return _size ? false : true;}template<class T>size_t MYStack<T>::Size(){return _size;}template<class T>void MYStack<T>::Print(){//size_t plen = q1.size();//while (plen--)//{//cout << q1.front() << " ";//q1.pop();//}size_t plen = q2.size();while (plen--){cout << q2.front() << " ";q2.pop();}plen = q1.size();while (plen--){cout << q1.front() << " ";q1.pop();}}

  注释掉的部分也可以实现,它的原理是不管第(3)步是出栈还是入栈,都把剩下的元素从Q2出栈入栈到Q1,输出的时候只用输出Q1中的元素。但是它的效率较低。如果有这种情况:1,2,3.....100000入栈,然后1,2,3......100000出栈,这会导致Q1和Q2频繁的出栈和入栈,效率非常之低。

  优化方法就是没有注释部分。它的实现就是入栈都是Q1入队列,出栈后不把Q2的元素移到Q1,这样的话效率就会提高,只是在输出的时候要先输出Q2里的元素,再输出Q1里的元素。因为Q1里的元素总是栈顶的元素。