栈实现表达式求值,队列应用
1.
2.
一、 源程序
1.
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
//去掉空格
string split(string s){
string ss;
for(int i=0;i<s.size();i++){
if(s[i]==32) continue;
ss+=char(s[i]);
}
return ss;
}
//判断是否缺括号
bool check1(string s){
int cnt=0;
for(int i=0;i<s.size();i++){
if(s[i]=='(') cnt++;
else if(s[i]==')') cnt--;
}
return cnt==0;
}
//判断运算符和数的合理性
bool check2(string s){
for(int i=0;i<s.size();i++){
if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/'){
if(i==0||i==s.size()-1||i&&(s[i-1]=='+'||s[i-1]=='-'||s[i-1]=='*'||s[i-1]=='/')){
return 0;
}
}
}
return 1;
}
int pri(char ch){return ch=='*'||ch=='/'?2:1;}
char ch[N];
int cnt;
string suan(string s){
string ss;
for(int i=0;i<s.size();i++){
if(s[i]>='0'&&s[i]<='9'){
ss+=char(s[i]);
}else{
if(s[i]=='('){
ch[cnt++]='(';
}else if(s[i]==')'){
while(ch[cnt-1]!='('){
ss+=ch[--cnt];
}
cnt--;
}else{
char c=char(s[i]);
if(cnt>0&&pri(c)<=pri(ch[cnt-1])){
while(cnt>0&&ch[cnt-1]!='('&&pri(c)<=pri(ch[cnt-1])){
ss+=ch[--cnt];
}
}
ch[cnt++]=c;
}
}
}
while(cnt>0){
ss+=ch[--cnt];
}
return ss;
}
int op(int x,int y,char ch){
if(ch=='+') return x+y;
else if(ch=='-') return x-y;
else if(ch=='*') return x*y;
else return x/y;
}
int a[N],ct;
int op(string s){
for(int i=0;i<s.size();i++){
if(s[i]>='0'&&s[i]<='9'){
a[ct++]=s[i]-48;
}
else{
int x=a[ct-2],y=a[ct-1];
ct-=2;
a[ct++]=op(x,y,char(s[i]));
}
}
return a[0];
}
int main(){
string s;
getline(cin,s);
s=split(s);
if(!check1(s)){
cout<<"ERROR:缺少括号";
return 0;
}
if(!check2(s)){
cout<<"ERROR:表达式缺操作数";
return 0;
}
string ss=suan(s);
cout<<ss<<endl;
cout<<op(ss);
return 0;
}
2.#include<bits/stdc++.h>
using namespace std;
int main() {
//VIP存储队列
list< string> listVIP;
//normal存储队列
list< string> listNormal;
string print;
string name;
string ID;
int M;
cin >> M;
while (M > 0) {
M--;
cin >> print;
if (print == "OUT") {
cin >> ID;
if (ID == "V") {
listVIP.pop_front();
} else {
listNormal.pop_front();
}
} else {
cin >> name >> ID;
if (ID == "V") {
listVIP.push_back(name);
} else {
listNormal.push_back(name);
}
}
}
for (const auto &s : listVIP) {
cout << s << endl;
}
for (const auto &s : listNormal) {
cout << s << endl;
}
return 0;
}
二、 个人体会(此部分与拼题a上主观题提交应一致)
7-2 栈实现表达式求值
1.问题是关于后缀表达式的生成和计算。我们需要将中缀表达式转换为后缀表达式,然后计算后缀表达式的值。这需要我们正确地处理运算符的优先级和括号的使用。
2.先创建一个空栈和一个空输出队列,从左到右扫描中缀表达式。
如果当前字符是一个数字,将其加入输出队列。
如果当前字符是一个左括号,将其压入栈。
如果当前字符是一个右括号,则将栈元素弹出并加入输出队列,直到遇到左括号为止。左括号只弹出而不加入输出队列。
如果当前字符是一个运算符(、+、-、*、/),o1,将其与栈顶运算符o2比较。如果o1优先级大于o2,或者o1是左括号,则将o1压入栈。否则,从栈弹出元素并加入输出队列,直到遇到优先级大于或等于o1的运算符或者左括号为止。然后将o1压入栈。
重复以上步骤直到扫描完整个中缀表达式。
将栈中所有元素弹出并加入输出队列。
输出队列中的元素就是转换后的后缀表达式。
3.实验设计思路
1)判断表达式是否正确,括号缺失的表达式,输出"ERROR:缺少括号"。输入两个除括号外运算符连续的表达式,输出"ERROR:表达式缺操作数"。
2)实现中缀表达式到后缀表达式的转换。遍历中缀表达式中的每个字符,若为数字则直接加入后缀表达式中,若为左括号则压入栈中,若为右括号则将栈中的运算符弹出并加入后缀表达式中,直到遇到左括号为止,左括号只弹出不加入后缀表达式。若为运算符,则与栈顶运算符比较优先级,若优先级大于栈顶运算符或为左括号,则将当前运算符压入栈中;否则从栈中弹出元素并加入后缀表达式,直到遇到优先级大于或等于当前运算符的运算符或左括号为止。
3)计算后缀表达式的值。从左到右遍历后缀表达式中的每个字符,若为数字则将其转换为整型并加入结果中,若为运算符则从栈中弹出两个操作数并计算其值,将结果加入结果中。
4)输出后缀表达式和结果。
实验后的感想:
首先,更加熟悉了栈的使用,通过使用栈,我们可以有效地处理括号和运算符优先级的问题,这是中缀表达式直接转换为后缀表达式所无法比拟的。
其次,我对表达式转换的过程有了更深入的理解。从中缀表达式到后缀表达式的转换是一个复杂的过程,通过实现这个转换,我增强了自己的编程技能,并对计算机科学原理有了更好的理解。
最后,我对如何设计和实现一个有效的后缀表达式有了更清晰的认识。后缀表达式是一种非常有效的计算方式,能够简化复杂的数学运算。 通过这个实验,我对如何设计和实现这样的计算器有了更清晰的认识。
总的来说,这个实验让我对计算机科学有了更深入的理解,并增强了我的编程技能。
7-2 队列应用(蓝桥杯)
1.实验设计思路:
初始化两个空队列vip_queue和normal_queue。
遍历M次操作:
如果是IN name V类型的操作,将用户加入vip_queue。
如果是OUT V类型的操作,将vip_queue队头的用户弹出并记录其姓名,同时将该用户加入normal_queue。
如果是IN name N类型的操作,将用户加入normal_queue。
如果是OUT N类型的操作,将normal_queue队头的用户弹出并记录其姓名。
遍历结束后,vip_queue中剩余的元素即为VIP窗口队列中的姓名,normal_queue中剩余的元素即为普通窗口队列中的姓名。
2.实验后的感想:
通过实现队列的操作,我不仅增强了自己的编程技能,还加深了对数据结构原理的理解。在解决这个问题时,我使用了队列来存储每个窗口的用户,并使用 IN 和 OUT 操作来模拟用户的进入和离开。此外,这个实验还让我意识到计算机科学在实际生活中的应用。在现实生活中,我们经常会遇到排队的情况,如银行、超市等。通过这个实验,我理解到计算机科学中的数据结构可以用来解决这些问题,使排队更加高效、有序。