栈的应用——括号、前缀后缀表达式

1.括号匹配问题

(((()))) ()()(())

最后出现的左括号会最先匹配(LIFO)所有括号都可以两两配对。

每出现一个右括号,就消耗一个左括号,出栈操作

遇到左括号就入栈,遇到右括号就“消耗”一个左括号出栈。

#define MaxSize 10
#include <Stack.cpp>


bool bracketChechk(char str[], int length){
    SqStack S;
    InitStack(S);
    for(int i=0; i<length; i++){
        if(str[i] == '(' ||str[i] == '['||str[i] == '{'){
            Push(S,str[i]);
        }else{
            if(StackEmpty(S))
                return false;
            char topElem;
            Pop(S,topElem);
            if(str[i]==')' && topElem !='(')
                return false;
            if(str[i]==']' && topElem !='[')
                return false;
            if(str[i]=='}' && topElem !='{')
                return false;
        }
    }
    return StackEmpty(S);
    
}

以上代码建立在栈基本操作基础上,可以看我专栏之前文章找栈。

2.算数表达式

eg:((15/(7-(1+1)))*3)-(2+(1+1))

由三个部分组成:操作数、运算符、界限符

在传统式子中,界限符是不可缺少的,它反映了计算的先后顺序

某波兰数学家想到了不用界限符,无歧义表达运算顺序

Reverse Polish  notation (逆波兰表达式=后缀表达式)

Polish notation(波兰表达式=前缀表达式)

中缀表达式 运算符在两个操作数中间  a+b   a+b-c         a+b-c*d

后缀表达式 运算符在两个操作数后面 ab+   ab+c-/abc-+    ab+ cd* -

前缀表达式 运算符在两个操作数之前 +ab   -+abc            -+ab*cd

(一个新的颜色可以理解为形成的一个新的数)

中缀转后缀:

由于转换可以由很多种,但算法有确定性,为保证运算顺序唯一,

所以转换时最好遵循左优先原则,只要左边能先计算,就优先算左边的)

同理后缀表达式手算方法:

从左往右扫描,每遇到一个运算符,就让运算符前面最近的两个操作数执行对应运算,合体为一个操作数。(注意除法之类的左右顺序)

中缀转前缀:

【运算符 左操作数 右操作数】组成新操作数

遵循 右优先原则 

3.用栈实现中缀转后缀

初始化一个栈,用于保存暂时还不能确定运算顺序的运算符。

从左到右处理各种元素,直到末尾。可能遇到三种情况:

(1)遇到操作数,直接加入后缀表达式

(2)遇到界限符, 遇到“(”直接入栈, 遇到“)”则依次餐厨栈内运算符并加入后缀表达式,直到弹出“( ”为止,注意:“(”不加入后缀表达式

(3)遇到运算符。依次弹出栈中优先级高于或等于当前运算符的所有运算符,并加入后缀表达式,若碰到“(”或栈空则停止。之后再把当前运算符入栈

最后,将栈中所有运算符弹出,并加入后缀表达式

4.用栈实现中缀表达式求值

(中缀转后缀+后缀表达式求和)

初始化两个栈,操作数栈和运算符栈

扫描到操作数——压入操作数栈

扫描到运算符或界限符,则按照“中缀转后缀”相同逻辑压入运算符栈

(期间也会弹出运算符。每当弹出一个运算符时,就需要弹出两个操作数栈的栈顶元素并执行相应运算,运算结果再压回操作数栈)

懒得写代码.jpg

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
不好意思,我看到你的问题是一样的,我之前回答的是解决中缀表达式转后缀表达式的问题,如果你想了解如何用解决中缀表达式转前缀表达式,可以参考以下思路: 1. 将中缀表达式倒序。 2. 将倒序后的中缀表达式中的左右括号互换。 3. 从右往左遍历倒序后的中缀表达式的每个元素。 4. 如果遇到操作数,直接输出。 5. 如果遇到右括号或运算符,将其压入中。 6. 如果遇到左括号,将中的元素依次弹出并输出,直到遇到右括号或运算符为止。将弹出的元素倒序输出。 7. 遍历完倒序后的中缀表达式后,将中剩余的元素依次弹出并输出。 8. 将输出的前缀表达式倒序即为原始中缀表达式的前缀表达式。 代码实现如下: ```c++ #include <iostream> #include <stack> #include <algorithm> using namespace std; int priority(char c) // 定义运算符优先级 { if (c == '+' || c == '-') return 1; if (c == '*' || c == '/') return 2; return 0; } void infixToPrefix(string infix) // 中缀表达式转前缀表达式 { reverse(infix.begin(), infix.end()); // 将中缀表达式倒序 stack<char> s; for (int i = 0; i < infix.length(); i++) { char c = infix[i]; if (isdigit(c)) cout << c; // 遇到操作数 else if (c == ')') s.push(c); // 遇到右括号 else if (c == '(') { // 遇到左括号 while (!s.empty() && s.top() != ')') { cout << s.top(); s.pop(); } s.pop(); // 弹出右括号 } else { // 遇到运算符 while (!s.empty() && priority(s.top()) >= priority(c)) { cout << s.top(); s.pop(); } s.push(c); } } while (!s.empty()) { // 将中剩余元素输出 cout << s.top(); s.pop(); } reverse(infix.begin(), infix.end()); // 将输出的前缀表达式倒序 } int main() { string infix = "1+2*(3-4)/5"; infixToPrefix(infix); return 0; } ``` 输出结果为:`+/1/*2-345`,即为转换后的前缀表达式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值