首页 > 编程语言 >C++U6-10 - 表达式与表达式求值

C++U6-10 - 表达式与表达式求值

时间:2024-03-30 15:56:44浏览次数:25  
标签:10 优先级 int s1 栈顶 运算符 求值 表达式 op

学习目标

 算数表达式

 三种算数表达式

 中缀转后缀

 

 计算机的转换逻辑

 中缀转后缀

 

【算法分析】
从左到右进行遍历。

1.遇到的是运算数,直接输出。

2.遇到的是左括号'(',直接压入堆栈(括号是最高优先级,无需比较;入栈后优先级降到最低,确保其他符号正常入栈)。

3.遇到的是右括号')',意味着括号已结束。不断弹出栈顶运算符并输出,直到遇到左括号,这个左括号弹出但是不输出。

4.遇到的是运算符('+'、'-'、'*'、'/'),有三种情况

①如果栈为空,直接入栈。

②如果栈顶元素是左括号'(',直接入栈。

③如果栈顶元素是运算符,则需要进行比较,

1-如果优先级大于栈顶运算符,则压入堆栈;

2-如果优先级小于等于栈顶运算符,则将栈顶运算符弹出并输出,然后比较新的栈顶运算符,直到优先级大于栈顶运算符或者栈空,再将该运算符入栈

5.如果对象处理完毕,则按顺序弹出并输出栈中所有运算符

【参考代码】
#include<bits/stdc++.h>
using namespace std;

const int maxSize = 109;
//判断运算符的优先级
int getPriority(char op) {
    if (op == '+' || op == '-')
        return 0; //+或-的优先级比较低
    else
        return 1;
}
void infixToPostFix(char infix[], char s2[], int& top2) //infix[]是中缀表达式存在数组里,s2是结果栈
{
    char s1[maxSize]; int top1 = -1; //s1是辅助栈
    int i = 0;
    while (infix[i] != '\0') {
        if ('a' <= infix[i] && infix[i] <= 'z') { //如果扫描到'a'-'z'字符,将它放入s2
            s2[++top2] = infix[i];
            ++i;
        }
        else if (infix[i] == '(') { //如果扫描到'(',将它放入s1
            s1[++top1] = '(';
            ++i;
        }
        else if (infix[i] == '+' || //如果扫描到'+','-','*','/'字符,需要和s1里的元素进行判断
            infix[i] == '-' ||
            infix[i] == '*' ||
            infix[i] == '/') {
            if (top1 == -1 || //判断s1是否为空
                s1[top1] == '(' || //判断辅助栈的栈顶元素是否为'('
                getPriority(infix[i]) > getPriority(s1[top1])) { //判断表达式里元素的优先级是否大于s1元素的优先级
                s1[++top1] = infix[i];
                ++i;
            }
            else //如果不是,将辅助栈的运算符放入结果栈里
                s2[++top2] = s1[top1--];
        }
        else if (infix[i] == ')') {
            while (s1[top1] != '(')
                s2[++top2] = s1[top1--];
            --top1; //删除s1里的'('
            ++i;
        }
    }
    while (top1 != -1)
        s2[++top2] = s1[top1--]; //将s1中的元素都放入s2
}
char s[109], res[109];
int main() {
    cin >> s;
    int len = -1;
    infixToPostFix(s, res, len);
    for (int i = 0; i <= len; i++) cout << res[i];
    return 0;
}
View Code

 

中缀表达式

 

 

 

[【表达式求值】中缀表达式转前缀表达式]

 

【算法分析】
中缀转前缀:

从右到左进行遍历。

1.遇到的是运算数,直接输出。

2.遇到的是右括号')',直接压入堆栈(括号是最高优先级,无需比较;入栈后优先级降到最低,确保其他符号正常入栈)。

3.遇到的是左括号'(',意味着括号已结束。不断弹出栈顶运算符并输出,直到遇到右括号,这个右括号弹出但是不输出。

4.遇到的是运算符('+'、'-'、'*'、'/'),有三种情况

①如果栈为空,直接入栈。

②如果栈顶元素是右括号')',直接入栈。

③如果栈顶元素是运算符,则需要进行比较,

1-如果优先级大于栈顶运算符,则压入堆栈;

2-如果优先级小于等于栈顶运算符,则将栈顶运算符弹出并输出,然后比较新的栈顶运算符,直到优先级大于等于栈顶运算符或者栈空,再将该运算符入栈

5.如果对象处理完毕,则按顺序弹出并输出栈中所有运算符

【参考代码】
#include<bits/stdc++.h>
using namespace std;

const int maxSize = 109;

//判断运算符的优先级
int getPriority(char op) {
    if (op == '+' || op == '-')
        return 0; //+或-的优先级比较低
    else
        return 1;
}
void infixToPreFix(char infix[], int len, stack<char>& s2) {
    stack<char> s1;//符号栈
    int i = len - 1;
    while (i >= 0) {
        if ('a' <= infix[i] && infix[i] <= 'z') {
            s2.push(infix[i]);
            --i;
        }
        else if (infix[i] == ')') {
            s1.push(infix[i]);
            --i;
        }
        else if (infix[i] == '+' || 
            infix[i] == '-' ||
            infix[i] == '*' ||
            infix[i] == '/') {
            if (s1.size() == 0 ||   
                s1.top() == ')' || 
                getPriority(infix[i]) > getPriority(s1.top())) {
                s1.push(infix[i]);
                --i;
            }
            else {
                s2.push(s1.top());
                s1.pop();
            }
                
        }
        if (infix[i] == '(') {
            while (s1.top() != ')') {
                s2.push(s1.top());
                s1.pop();
            }
            s1.pop();
            --i;
        }
    }
    while (s1.size()) {
        s2.push(s1.top());
        s1.pop();
    }
}
char s[109];
stack<char> res;
int main() {
    cin >> s;
    int len = -1;
    infixToPreFix(s, strlen(s), res);
    while (res.size()) {
        cout << res.top();
        res.pop();
    }
    return 0;
}
View Code

 

 

后缀表达式求值

 

 

后缀表达式求值

 

【算法分析】
从左到右扫描,碰到数字就进栈,碰到操作数就拿出栈顶的两个元素就行运算,栈顶应该是右操作数。

【参考代码】
#include<bits/stdc++.h>
using namespace std;

int main() {
    string s;
    cin >> s;
    stack<int> num;
    for (int i = 0; i < s.length(); i++) {
        if (s[i] >= '0' && s[i] <= '9') {
            num.push(s[i] - '0');
        }
        else {
            int r = num.top(); num.pop();
            int l = num.top(); num.pop();
            if (s[i] == '+') num.push(l + r);
            else if (s[i] == '-') num.push(l - r);
            else if (s[i] == '*') num.push(l * r);
            else num.push(l / r);
        }
    }
    cout << num.top();
    return 0;
}
View Code

 

 

前缀表达式求值

 

 

【表达式求值】前缀表达式求值]

 

【算法分析】
从右向左遍历整个字符串,碰到数字就进栈,碰到操作符就进行运算。

【参考代码】
#include<bits/stdc++.h>
using namespace std;

int main() {
    string s;
    cin >> s;
    stack<int> st;
    for (int i = s.length()-1; i >= 0; i--) {
        if (s[i] >= '0' && s[i] <= '9') {
            st.push(s[i] - '0');
        }
        else {
            int l = st.top(); st.pop();
            int r = st.top(); st.pop();
            if (s[i] == '+') {
                st.push(l + r);
            }
            else if (s[i] == '-') {
                st.push(l - r);
            }
            else if (s[i] == '*') {
                st.push(l * r);
            }
            else if (s[i] == '/') {
                st.push(l / r);
            }
        }
    }
    cout << st.top();
    return 0;
}
View Code

  

 

[【表达式求值】中缀表达式求值]

 

【算法分析】
从左到右扫描该中缀表达式:

如果遇到数字,直接输出该数字。
如果遇到左括号,那么将其放在运算符栈上。
如果遇到右括号,不断输出栈顶元素,直至遇到左括号,左括号出栈。换句话说,执行一对括号内的所有运算符。
如果遇到其他运算符,不断输出所有运算优先级大于等于当前运算符的运算符。最后,新的运算符入运算符栈。
在处理完整个字符串之后,一些运算符可能仍然在堆栈中,因此把栈中剩下的符号依次输出,表达式转换结束。
【参考代码】
#include<bits/stdc++.h>
using namespace std;

stack<int> num;
stack<char> op;
int getPriority(char op) {
    if (op == '+' || op == '-')
        return 0; //+或-的优先级比较低
    return 1;
}
void calc() {
    int r = num.top(); num.pop();//栈顶是右操作数
    int l = num.top(); num.pop();//次栈顶是左操作数
    if (op.top() == '+') num.push(l + r);
    if (op.top() == '-') num.push(l - r);
    if (op.top() == '/') num.push(l / r);
    if (op.top() == '*') num.push(l * r);
    op.pop();//弹出运算符
}
int main() {
    string s;
    cin >> s;
    for (int i = 0; i < s.length(); i++) {
        if (s[i] >= '0' && s[i] <= '9') {
            num.push(s[i] - '0');
        }
        else {
            if (s[i] == '(') {
                op.push(s[i]);//左括号直接进栈
            }
            else if (s[i] == '+'||s[i]=='-'||s[i]=='*'||s[i]=='/') {
                while (op.size() && op.top()!='('&&getPriority(op.top()) >= getPriority(s[i])) {
                    calc();
                }
                op.push(s[i]);
            }
            else if (s[i] == ')') {
                while (op.top() != '(') {
                    calc();
                }
                op.pop();//弹出左括号
            }
        }
    }
    while (op.size()) {
        calc();
    }
    cout << num.top();
    return 0;
}
View Code

 

作业讲解分析:

链接:https://pan.baidu.com/s/1kC35E12wnWnlylu1KIuq9g?pwd=q55c
提取码:q55c

 

标签:10,优先级,int,s1,栈顶,运算符,求值,表达式,op
From: https://www.cnblogs.com/jayxuan/p/18105597

相关文章

  • 20211105李宜时DER
    作业内容:参考附件中图书p120中7.1的实验指导,完成DER编码Name实例中,countryName改为“CN”,organizationName-"你的学号"commoaName="你的姓名拼音"用echo-n-e"编码">你的学号.der中,用OpenSSLasn1parse分析编码的正确性提交编码过程文档(推荐markdown格式)具体过程......
  • Acwing 1050. 鸣人的影分身
    https://www.acwing.com/problem/content/1052/输入样例:173输出样例:8#include<bits/stdc++.h>usingnamespacestd;typedeflonglongLL;typedefpair<int,int>PII;constLLMAXN=1e18,MINN=-MAXN,INF=0x3f3f3f3f;constLLN=200200,M=2020;LLn,m;LL......
  • linux正则表达式之*
    1.*含义linux正则表达式*表示重复0个或多个前一个重复字符2.样例正则表达式*样例命令:grep-n"min*"anaconda-ks.cfg#找出含有mi、min、minn等字符串的行。注:因为*可以是0个,所以mi也是符合搜索字符串,另外,因为*为重复前一个字符的符号,因此,在*之前必须要紧挨着一个重复字......
  • 1071 - Specified key was too long; max key length is 767 bytes
    1071-Specifiedkeywastoolong;maxkeylengthis767bytes问题背景问题分析处理问题背景今天在Mysql建表的过程中,遇到了一个这样的问题,错误信息1071-Specifiedkeywastoolong;maxkeylengthis767bytes下面来分析如何处理问题分析处理根据错误......
  • 语法回顾-《Verilog编程艺术》之表达式
    目录表达式操作符操作符优先级整数算数操作符比较操作符逻辑操作符位运算操作符归约操作符移位操作符条件操作符连接操作符操作数向量的抽取数组的访问字符串表达式位长符号表达式赋值和截断与x/z比较参考《Verilog 编程艺术》魏家明著表达式表达式是......
  • LC 104.二叉树的最大深度
    104.二叉树的最大深度给定一个二叉树root,返回其最大深度。二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。示例1:输入:root=[3,9,20,null,null,15,7]输出:3示例2:输入:root=[1,null,2]输出:2提示:树中节点的数量在......
  • C语言程序10题
    第71题(10.0分)       难度:易       第1章/*-------------------------------------------------------【程序填空】---------------------------------------------------------功能:求100-999之间的水仙花数说明:水仙花数是指一个三位数的各位数字的立......
  • SQL88 返回订单数量总和不小于100的所有订单的订单号(group(),having..)
    selectorder_numfromOrderItemsgroupbyorder_numhavingsum(quantity)>=100orderbyorder_num;......
  • OWASP10
    访问控制崩溃未对通过身份验证的用户实施恰当的访问控制。攻击者可以利用这些缺陷访问未经授权的功能和数据,例如:访问其他用户的账户、查看敏感文件、修改其他用户的数据、更改访问权限等。eg:零元购通过修改URL、内部应用程序状态或HTML页面绕过访问控制检查,或简单地使用自定义......
  • 【洛谷】P1060 开心的金明
    P1049装箱问题确认所需算法题目链接:P1060开心的金明这题是一道01背包问题,如果你还不知道什么是背包问题,那么请看我的背包问题学习笔记思路这道题的输入有一点点奇怪,v[i]=2~n+1行的第一个数*第二个数。其他的稍微抽象一点就可以变为标准的01背包问题了。关于状态转移方程......