栈解决括号匹配和后缀表达式的计算问题
前言
存储货物或供旅客住宿的地方,可引申为仓库、中转站 。例如我们现在生活中的酒店,在古时候叫客栈,是供旅客休息的地方,旅客可以进客栈休息,休息完毕后就离开客栈。我们把生活中的栈的概念引入到计算机中,就是供数据休息的地方,它是一种数据结构,数据既可以进入到栈中,又可以从栈中出去。
一、栈
栈是一种基于先进后出(FILO)的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。我们称数据进入到栈的动作为压栈,数据从栈中出去的动作为弹栈。
二、括号匹配问题
- 问题描述
检测括号是否一一对应,一个左括号"(",必须对应一个右括号")",且对应顺序一致。 - 利用栈解决该问题的思路
- Java代码实现
// 利用栈 解决括号是否匹配问题
public class BracketMatch {
public static void main(String[] args) {
String s="(mekeater(sun))";
boolean b = IsMatch(s);
System.out.println("字符串 "+s +"中的括号是否匹配:"+b);
}
private static boolean IsMatch(String s)
{
//1. 创建栈
Stack<String> chars = new Stack<>();
//2. 遍历字符串
for (int i = 0; i < s.length(); i++) {
//3. 如果字符为左括号(,则入栈
String c = s.charAt(i)+"";
if (c.equals("("))
chars.push(c);
//4. 否则判断字符为右括号),若是,则弹栈并判断弹出元素是否为null,若为null则不匹配,否则,继续遍历
else if(c.equals(")"))
{
String pop = chars.pop();
if (pop==null)
return false;
}
}
//5. 遍历完成,判断栈中是否还有元素,若有,则不匹配
if (chars.size()!=0)
return false;
else
return true;
}
}
三、后缀表达式计算问题
- 中缀表达式
中缀表达式就是我们平常生活中使用的表达式,例如:1+3*2,2-(1+3)等等,中缀表达式的特点是:二元运算符总是置于两个操作数中间。
中缀表达式是人们最喜欢的表达式方式,因为简单,易懂。但是对于计算机来说就不是这样了,因为中缀表达式的运算顺序不具有规律性。不同的运算符具有不同的优先级,如果计算机执行中缀表达式,需要解析表达式语义,做大量的优先级相关操作。 - 后缀表达式(逆波兰表达式)
后缀表达式的特点:运算符总是放在跟它相关的操作数之后。
- 问题描述
如何解决后缀表示的计算问题,以中缀表达式 6*(12-9)+27/9的计算为例,转换为后缀表达式即是: 6 12 9 - * 27 9 / + - 利用栈计算后缀表达式的思路
- Java代码实现
// 利用栈,解决后缀表达式的计算问题
public class PostfixNotation {
public static void main(String[] args) {
// 中缀表达式 6*(12-9)+27/9, 后缀表达式 6 12 9 - * 27 9 / +
String[] notation={"6","12","9","-","*","27","9","/","+"};
int result = calculate(notation);
System.out.println("后缀表达式计算结果为: " + result);
}
private static int calculate(String[] notation)
{
//1. 创建栈
Stack<Integer> stack = new Stack<>();
//2. 遍历表达式
for (int i = 0; i < notation.length; i++) {
String curr = notation[i];
//3. 如果为操作数,则入栈
//4. 如果为操作符,则出栈两个元素,并与操作符进行计算,计算结果入栈
Integer o1;
Integer o2;
Integer result;
switch (curr)
{
case "+":
o1=stack.pop();
o2=stack.pop();
result=o2+o1;
stack.push(result);
break;
case "-":
o1=stack.pop();
o2=stack.pop();
result=o2-o1;
stack.push(result);
break;
case "*":
o1=stack.pop();
o2=stack.pop();
result=o2*o1;
stack.push(result);
break;
case "/":
o1=stack.pop();
o2=stack.pop();
result=o2/o1;
stack.push(result);
break;
default:
stack.push(Integer.parseInt(curr));
break;
}
}
//5. 栈中最后一个元素就是后缀表达式的计算结果
Integer over = stack.pop();
return over;
}
}