前言
在前面荔枝已经梳理了栈的定义和几个代码示例,在这篇文章中荔枝主要介绍了辅助栈的用法和用栈来实现一个简单的计算器应用。
目录
一、逆波兰表达式
1.1 定义
逆波兰表达式又被成为后缀表达式,表达式中的运输符位于操作数后。举个例子,现在我给出一个表达式“3 4 + 5 * 2 -”,这个就相当于(3+4)*5-2=33。我们可以用上一篇文章中对栈的认识来更清晰的了解这个表达式的意义。总结起来就是:我们将操作数入栈,遇到运算符则弹出两个操作数来运算,结果依旧要压入栈中,这样就可以实现逆波兰表达式的运算了。
当然了,与后缀表达式相对应的还有前缀表达式、中缀表达式。前缀表达式是运算符位于操作数前,而中缀表达式则是我们日常所用的一种表示方法。
需要注意的是:在对后缀表达式进行运算操作时我们采用从左到右的方式进行栈操作,对于前缀表达式我们则使用从右到左的方式进行栈操作。
1.2 问题示例
描述
给定一个逆波兰表达式,求表达式的值。
数据范围:表达式长度满足 1≤n≤10^4 ,表达式中仅包含数字和 + ,- , * , / ,其中数字的大小满足∣val∣≤200 。
输入样例:
["2","1","+","4","*"]输出样例:12
同样的,荔枝这里也只给出核心代码:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param tokens string字符串vector
* @return int整型
*/
int evalRPN(vector<string>& tokens) {
// write code here
stack<int> s;
for(int i=0;i<tokens.size();i++){
if(tokens[i]=="+"||tokens[i]=="-"||tokens[i]=="*"||tokens[i]=="/"){
int t2=s.top();
s.pop();
int t1=s.top();
s.pop();
if(tokens[i]=="+") s.push(t1+t2);
if(tokens[i]=="-") s.push(t1-t2);
if(tokens[i]=="*") s.push(t1*t2);
if(tokens[i]=="/") s.push(t1/t2);
}else{
int k = stoi(tokens[i]);
s.push(k);
}
}
return s.top();
}
};
二、计算器示例
我们先来看看题目要求吧,题目要求我们实现一个整数计算器,输入的数据氛围会在0和100之间,看到这种类型我们首先想到的就是用栈来实现,这里我主要是用两个栈来实现。一个栈是用来存储数据的,一个则是用来存储运算符的,最后的值是储存在数字栈result中的。
题目示例
描述
请写一个整数计算器,支持加减乘三种运算和括号。
数据范围:0≤∣s∣≤100,保证计算结果始终在整型范围内
输入示例:
"(2*(3-4))*5"
输出示例:
-10
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
map<char, int> m_map = {{'-', 1},{'+', 1},{'*', 2},{'/', 2},{'%', 2}}; //记录每种运算符的权重
stack<int> result; //数字栈
stack<char> y; //运算符栈
void fun(){ //这个函数实现了运算的过程
if(result.empty() || result.size() < 2) return ;
if(y.empty()) return;
char key = y.top();
y.pop();
int n1 = result.top();
result.pop();
int n2 = result.top();
result.pop();
switch(key){
case '+':
result.push(n1+n2);
break;
case '-':
result.push(n2-n1);
break;
case '*':
result.push(n1*n2);
break;
}
}
int solve(string s) {
// write code here
int num = 0;
for(int i=0;i<s.length();i++){
//数字转换成int数字
if(isdigit(s[i])){
num = 10*num + (s[i] - '0');
while(i + 1<s.length() && isdigit(s[i+1]))
{
i++;
num = 10*num + (s[i] - '0');
}
result.push(num);
num = 0;
}
else if(s[i]=='('){ //遇到"("的时候需要判断下一个元素是否为负数,若是就在result栈里压入一个0
y.push(s[i]);
if(i<s.length() && s[i+1]=='-'){
result.push(0);
y.push(1);
i++;
}
}
else if(s[i]=='+'||s[i]=='-'||s[i]=='*'){ //我们在将每一个运算符压入栈之前需要判断当前运算符是否小于栈顶的运算符的权重,如果是那么要先将栈里面的运算符进行运算
while(!y.empty() && y.top() != '(' && m_map[s[i]] <= m_map[y.top()])
{
fun();
}
y.push(s[i]);
}
else if(s[i]==')'){
while(y.top() != '(')
{
fun();
}
y.pop();
}
}
while(!y.empty()) fun();//解决表达式中没有括号不运算的问题
return result.top();
}
};
总结
荔枝在上面主要还是记录了栈的两种经典的题目,特别是计算器应用的实现对于理解清楚栈的功能有极大的帮助。明天就要真的来刷题啦,先把STL灵活掌握再来整理啦,希望明天闹钟叫得醒我哈哈哈,时间不多一起加油吧~
今朝已然成为过去,明日依然向往未来!我是小荔枝,在技术成长的路上与你相伴,码文不易,麻烦举起小爪爪点个赞吧哈哈哈。
谢谢大家的支持嘻嘻嘻~~~
比心心♥~~~