题目
实验二 堆栈模拟队列
- 实验目的
1、复习C/C++语言程序设计中的知识。
2、熟悉栈和队列的逻辑结构。
3、熟悉栈和队列的基本运算在两种存储结构上的实现,其中以熟悉栈和队列的操作为侧重点。
- 实验内容和要求
[问题描述]
设已知有两个堆栈S1和S2,请用这两个堆栈模拟出一个队列Q。
所谓用堆栈模拟队列,实际上就是通过调用堆栈的下列操作函数:
- int IsFull(Stack S):判断堆栈S是否已满,返回1或0;
- int IsEmpty (Stack S ):判断堆栈S是否为空,返回1或0;
- void Push(Stack S, ElementType item ):将元素item压入堆栈S;
- ElementType Pop(Stack S ):删除并返回S的栈顶元素。
实现队列的操作,即入队void AddQ(ElementType item)和出队ElementType DeleteQ()。
[基本要求]
(1)输入首先给出两个正整数N1和N2,表示堆栈S1和S2的最大容量。随后给出一系列的队列操作:A item表示将item入列(这里假设item为整型数字);D表示出队操作;T表示输入结束。
(2)对输入中的每个D操作,输出相应出队的数字,或者错误信息ERROR:Empty。如果入队操作无法执行,也需要输出ERROR:Full。每个输出占1行。
[测试数据]
3 2
A 1 A 2 A 3 A 4 A 5 D A 6 D A 7 D A 8 D D D D T
[实现提示]
使用两个栈对数据进行一定的出入栈操作,模拟出出入对数据的顺序。
算法设计
1、主要思想:
1.当输入字符A时,将其后输入的数字入栈;
① s1没满直接压入s1;
② s1满了,弹出元素压入s2中,新元素压入s1中;
③ 其他情况输出Full;
2.当输入字符D时,将调用出栈函数;
① s2不空时,直接出;
② s2空,将s1中元素弹出压入s2中,最后在出栈;
③ 其他情况输出Empty;
3. 当输入字符T时,结束程序。
以题中所给测试数据为例,下表是具体操作过程
表一
步骤 | S1 | S2 |
1 | 1 | Empty |
2 | 1 2 | Empty |
3 | 1 | 2 |
4 | Empty | Empty |
5 | 3 | Empty |
6 | 3 4 | Empty |
7 | 3 | 4 |
8 | Empty | Empty |
9 | 5 | Empty |
10 | 5 6 | Empty |
11 | 5 | 6 |
12 | Empty | Empty |
13 | 7 | Empty |
14 | 7 8 | Empty |
15 | 7 | 8 |
16 | Empty | Empty |
2、本程序包含三个模块
2.1 准备工作——主函数接收数据
1.接收到两个栈的长度时,首先应判断大小,s2长度应大于s1;
2.使用while循环接收字符,根据字符接收数据调用相应函数;
int main()
{
cin>>m1>>m2;
int t;
if(m1>m2)
{
t=m1;
m1=m2;
m2=t;
}
char ch;
while(cin>>ch)//接收指令字符
{
if(ch=='T')break;
else if(ch=='A')
{
cin>>n;
AddQ(n);//模拟入队
}
else DeleteQ();//模拟出队
}
return 0;
}
2.2 模拟入队操作
1.s1没满直接压入s1;
2.s1满了,弹出元素压入s2中,新元素压入s1中;
3.其他情况输出Full;
void AddQ(int n)
{
if(s1.size()!=m1)//s1栈不满直接入栈
{
s1.push(n);
}
else if(s2.empty())//s1栈满时将s1中的数据压到s2中
{
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
s1.push(n);
}
else cout<<"ERROR:Full"<<endl;//若不能执行输出报错
}
2.3模拟出队操作
1.s2不空时,直接出;
2.s2空,将s1中元素弹出压入s2中,最后在出栈;
3.其他情况输出Empty;
void DeleteQ()
{
if(!s2.empty())//s2不空时,直接出;
{
cout<<s2.top()<<endl;
s2.pop();
}
else if(!s1.empty())//s2空,将s1中元素弹出压入s2中,最后在出栈;
{
while(s1.size()!=1)
{
s2.push(s1.top());
s1.pop();
}
cout<<s1.top()<<endl;
s1.pop();
}
else cout<<"ERROR:Empty"<<endl; //若不能执行输出报错
}
- 实验结果
1.输入3 2
A 1 A 2 A 3 A 4 A 5 D A 6 D A 7 D A 8 D D D D T,输出结果如图1所示。
图1 实验结果
- 算法性能分析
(1)时间复杂度: 此算法从头到尾读入每个字符,若字符总长度为n,则此算法的时间复杂度为O(n)。
(2)空间复杂度:此算法在运行时所占用的空间取决于栈的大小,显然 ,他们的空间大小之和不会超过n,所以此算法的空间复杂度为O(n)。
- 总结
此次上机实验应用了栈实现了一次实际操作,完成了通过控制出入栈条件,实现了两个栈去模拟对列,不仅对此次编译程序的算法思想有了新的认识,还让我深刻地体会到了栈和队列的重要性以及其应用的方便,并且对栈和队列加深了印象,应用了书本中的算法思想,对我以后的编译以及完成新的程序有很大的帮助。
- 源程序(带注释)
#include <bits/stdc++.h>
using namespace std;
stack<int> s1;
stack<int> s2;
int m1,m2,n;
void AddQ(int n)
{
if(s1.size()!=m1)//s1栈不满直接入栈
{
s1.push(n);
}
else if(s2.empty())//s1栈满时将s1中的数据压到s2中
{
while(!s1.empty())
{
s2.push(s1.top());
s1.pop();
}
s1.push(n);
}
else cout<<"ERROR:Full"<<endl;//若不能执行输出报错
}
void DeleteQ()
{
if(!s2.empty())//s2不空时,直接出;
{
cout<<s2.top()<<endl;
s2.pop();
}
else if(!s1.empty())//s2空,将s1中元素弹出压入s2中,最后在出栈;
{
while(s1.size()!=1)
{
s2.push(s1.top());
s1.pop();
}
cout<<s1.top()<<endl;
s1.pop();
}
else cout<<"ERROR:Empty"<<endl; //若不能执行输出报错
}
int main()
{
cin>>m1>>m2;
int t;
if(m1>m2)
{
t=m1;
m1=m2;
m2=t;
}
char ch;
while(cin>>ch)//接收指令字符
{
if(ch=='T')break;
else if(ch=='A')
{
cin>>n;
AddQ(n);//模拟入队
}
else DeleteQ();//模拟出队
}
return 0;
}