我们知道,栈的特点是先进后出,而队列的特点是先进先出,那么如何用先进后出的栈来完成队列的先进先出的操作呢?很明显,用一个栈是不能实现的,因此我们需要一个辅助栈来配合主栈完成。
假设我们先把元素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

391

被折叠的 条评论
为什么被折叠?



