用两个栈实现队列

我们知道,栈的特点是先进后出,而队列的特点是先进先出,那么如何用先进后出的栈来完成队列的先进先出的操作呢?很明显,用一个栈是不能实现的,因此我们需要一个辅助栈来配合主栈完成。

假设我们先把元素A、B、C、D压栈压到主栈stack1中,那么此时主栈中的元素就为{A,B,C,D},其中A为栈底元素,D为栈顶元素。如果此时我们需要删除元素,按照队列先进先出的原则,我们应该删除元素A,但此时元素A位于主栈的栈底,很明显不能直接删除,这时候我们就需要使用辅助栈stack2来完成。如果我们依次把主栈stack1中的元素弹出并压栈到辅助栈stack2中,则经过四次弹栈与压栈的操作后,元素在stack2中的顺序恰好和stack1中的顺序相反,即栈顶元素为A,栈底元素为D,而主栈stack1为空,这个时候我们就可以弹出辅助栈栈顶的元素A了,达到了删除的目的。删除之后,辅助栈中的元素为{B,C,D},栈顶元素为B,主栈仍然为空。此时如果我们想继续删除元素的话,我们发现,由于在压栈的时候,B比C更先进入,而且根据队列先进先出的规则,我们自然而然要先删除元素B了,而此时在辅助栈stack2中,元素B正好位于栈顶,则直接删除即可,删除后辅助栈的元素为{C,D},主栈仍然为空。还想继续删除元素的话操作也一样。

由此我们发现删除元素的步骤:当辅助栈stack2中不为空时,在stack2中的栈顶元素是最先进入队列的元素,那么就可以直接弹栈删除。如果stack2为空时,我们需要把主栈stack1中的元素逐个弹栈并压入stack2中。由于先进队列的元素被压到stack1的底部,经过弹出和压入操作之后就处于stack2的顶端了,就可以直接弹出。

那如果此时我们还需要继续插入元素E呢?同样的,将元素E压入主栈stack1中,此时主栈中只有一个元素{E},辅助栈stack2中仍然有元素{C,D}。当下一次我们考虑删除队列头部元素的时候,发现C和D比E都先进入队列,则直接在辅助栈stack2中弹栈即可,在删除元素E之前,C和D都应该在此之前删除。

图解为:

(1)首先将元素A,B,C,D压栈入主栈stack1中,辅助栈stack2暂时为空。压栈后的主栈中,栈顶元素为D,栈底元素为A。

 (2)接下来准备删除元素。删除元素之前先把stack1中的元素依次弹栈并压入stack2中。然后依次删除A和B元素。由于删除队列首元素A的时候,A刚好位于stack2的顶部,则直接弹栈即可。接着再想删除队列首元素的时候发现此时的队列首元素B也刚好位于stack2的顶部,也直接弹栈即可。

 (3)此时我们再看另一种情况,即如果想再插入元素的话。看是否插入之后再删除的话是否会有矛盾。如下图所示,我们发现,插入元素的时候仍然将元素压入主栈stack1中,此时并不影响后续删除队列元素的弹栈操作。

相关代码如下:

class Solution
{
public:
    //入队操作
    void push(int element)
    {
	stack1.push(element);
    }
    //出队操作
    int pop()
    {
	//如果辅助栈为空,则将stack1中元素依次弹出并压入此栈中
	if (stack2.empty())
	{
	    while (!stack1.empty())
	    {
		stack2.push(stack1.top());
		stack1.pop();
	    }
	}
	if (stack2.empty())
	{
	    cout << "Stack2 is empty!" << endl;
	}
	int head = stack1.top();
	stack2.pop();
	return head;
    }
private:
    stack<int> stack1;
    stack<int> stack2;
};

完整代码如下:

queue.h

#include <iostream>
#include <stack>
using namespace std;
class Queue
{
private:
    stack<int> stack1;		//主栈
    stack<int> stack2;		//辅助栈
public:
    //入队操作
    void Push(int element);
    //出队操作
    void Pop();
    //返回队首元素
    int Front();
    //返回队尾元素
    int Back();
    //判断队列是否为空
    bool Empty();
    //返回队列大小
    int Size();
};

queue.cpp

#include "queue.h"

//入队
void Queue::Push(int element)
{
    //主栈stack1作队列的队尾,stack2作为队列的队头
    stack1.push(element);
    cout << element << " ";
}

//出队
void Queue::Pop()
{
    while (!stack1.empty())
    {
	int element = stack1.top();
	stack2.push(element);
	stack1.pop();
    }
    stack2.pop();
}

//返回队首元素
int Queue::Front()
{
    while (!stack1.empty())
    {
	stack2.push(stack1.top());
	stack1.pop();
    }
    int temp = stack2.top();
    while (!stack2.empty())
    {
	int x = stack2.top();
	stack1.push(x);
	stack2.pop();
    }
return temp;
}

//返回队尾元素
int Queue::Back()
{
    return stack1.top();
}

//判断队列是否为空
bool Queue::Empty()
{
    if (stack1.empty() && stack2.empty())
    {
	return true;
    }
    else
    {
	return false;
    }
}

//返回队列大小
int Queue::Size()
{
    return stack1.size() + stack2.size();
}

int main()
{
    Queue q;
    cout << "入队操作,插入到队列的元素分别是:";
    q.Push(1);
    q.Push(2);
    q.Push(3);
    q.Push(4);
    q.Push(5);
    q.Push(6);
    cout << endl;
    cout << "队列是否为空:";
    if (q.Empty())
    {
	cout << "是" << endl;
    }
    else
    {
	cout << "否" << endl;
    }
    cout << "队首元素是:" << q.Front() << endl;
    cout << "队尾元素是:" << q.Back() << endl;
    cout << "队列大小为:" << q.Size() << endl;
    cout << "出队操作:" << endl;
    q.Pop();
    cout << endl;
    return 0;
}

 更多详细内容还请访问https://blog.csdn.net/lixiaogang_theanswer/article/details/72539997

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值