逆波兰数:逆波兰数由两部分组成(操作数,操作符)——是波兰表达式的一种,即操作符在操作数的后面。
形式:A+B*C-D = ABC*D-;
(A+B)*C-D = AB+C*D-;
既然我们知道了,后缀表达式那我们表达式是唯一的吗?我们来看一组数据:
例如:(A+B)*C-D 和 C*(A+B)-D;
很显然第二个的表达式为:C*AB+D-;虽然对最后的结果无影响,但我们需要知道逆波兰的多样性。
注意事项:
1、如果出现1+23 = 123+,该如何判断它的数值呢?
可以利用分割符来进行很好的辅助性理解,例如1+23 = 1#23#+,这样可以完美的解决此问题。
2、存在括号的时候该如何处理?
其一:是‘(’直接压入,‘)’时,将两者之间的运算符弹出,压入后缀表达式。
其二:遇到‘(’开辟一个新的运算符栈,‘)’时,当前栈内运算符弹出,压入后缀表达式。
算法:
1、中缀表达式——逆波兰表达式的转变。
- 准备一个栈一个链表,链表用来存操作数,栈用来存操作符。
- 如果为操作数,我们继续判断它的下一位是否也为操作数,是——则继续压入,否——压入分隔符(“#”)。同时判断字符栈中,是否为“*”,“/”,字符弹出,压入数值链表。
- 如果为操作符,直接压入字符栈。
- 如果‘(’,重新开辟一个新字符栈,其它操作相同。
- 如果‘ )’,将当前字符栈内部的字符逐个弹出,压入数值链表。
2、逆波兰求值。
- 准备一个栈,用来逐个求当前值。
- 依次取出数值链表的第一个值。
- 根据加减乘除运算做出相应的操作,即取出当前栈的前两个值,做运算符操作。
- 如果是操作数,我们继续判断它的下一位是否也为操作数,是——n*10+char-‘0’,否——压入栈中;
- 最后的到栈顶元素,即为运算后的值。
核心代码:
1、中缀表达式——逆波兰表达式的转变。
bool is_char(char c)//判断是否为操作符 { return c == ‘-‘ || c == ‘+‘ || c == ‘*‘ || c == ‘/‘; } void change()//表达式的转化 { char c; int i = 0, j = 0;//i遍历输入的字符,j不同层数的字符栈 while ((c = original[i++]) != ‘\0‘) { if (is_char(c))//是字符 one[j].push(c); else if (is_number(c))//是数字 { int x = i;// while (is_number(c)) { sconed.push_back(c); if (is_number(c = original[x++]))//是数值,则数组往后移动一位(确保下一步能读取字符) i++; } sconed.push_back(‘#‘);//分隔符 if (!one[j].empty())//判断是否为空 if (one[j].top() == ‘*‘ || one[j].top() == ‘/‘)//高阶运算,直接取出,压入数值链表 { sconed.push_back(one[j].top()); one[j].pop(); } } else if (c == ‘)‘) { Dum(j);//多余的运算符赋值 j--;//回到上一层的字符栈 } else j++;//新的字符栈 } Dum(j); } void Dum(int j)//多余的运算符逐个压入数值链表 { while (!one[j].empty()) { sconed.push_back(one[j].top()); one[j].pop(); } }
2、逆波兰求值。
void Do_it(std::stack<int> &mc) { while (!sconed.empty())//不为空时。 { char mid = sconed.front();//临时存储字符 sconed.pop_front();//压出 switch (mid)//判断 { int a, b; case‘-‘: b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行减法运算。 mc.push(a - b); break; case‘+‘: b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行加法运算。 mc.push(a + b); break; case‘*‘: b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行乘法运算。 mc.push(a * b); break; case‘/‘: b = mc.top(), mc.pop(), a = mc.top(), mc.pop();//得到前两个数值进行除法运算。 if (b == 0)//分母不能位0 { is_right = false; return; } else mc.push(a / b); break; default://获得数值 { int sum = 0; if (is_number(mid)) { while (is_number(mid)) { sum = sum * 10 + mid - ‘0‘;//字符到数字的改变 mid = sconed.front(); if (is_number(mid)) sconed.pop_front(); } mc.push(sum); } } } } }
Do_it
3、GitHub源码;
时间: 2024-08-29 05:13:24