逆波兰表达式的实现
╮(╯▽╰)╭,刚刚宿舍又熄灯了,今天又犯懒了,本来是想偷懒的,想想还是坚持下吧,又不是什么坏事情,,,摸着瞎瞎来写博客咯~~~,今天就开始结合着代码再将逆波兰表达式的转化问题复习一遍,之前的转化规则再抓过来看看,
<span style="font-size:14px;">1. 正式的开始转化,首先第一个规则就是,遇到数字直接加入到后缀表达式中。(比如第一个数字 9 直接写出)
2. 第二个规则是碰到运算符,需要做不同的处理。
① 若当前符号堆栈为空,则直接入栈。
② 若是 ‘(’ 就直接将其压入栈中,不管符号堆栈是否为空,也是直接入栈。
③ 若当前符号栈中已经有元素了,则弹出栈顶符号,和遇到的那个符号比较运算优先级(不算括号)。
Ⅰ.弹出的运算符优先级大,则将弹出的运算符写入后缀表达式,再重复步骤③
Ⅱ.弹出的运算符优先级小或者等于,则将弹出的运算符压入栈中,再将遇到的运算符也压入栈中。
Ⅲ.弹出的运算符为‘ ( ’,则先压入 ‘(’,再压入遇到的那个符号
④ 若碰到了‘ )’,则不停的从符号栈中弹出运算符至后缀表达式中,直到遇到第一个与之匹配的‘(’为止。这个过 程将中缀表达式中的括号直接去除,这也是后缀表达式的优势。</span>
再转化的过程中是需要一个栈,来存放所遇到的运算符,因此,首先需要弄一个栈类,下面直接上代码,代码中的注释会做详细的解释:
/**
* Created by dada on 14-11-19.
* 中缀转换后缀时用到的栈
* 根据我自己的理解
* 这个栈就是将数据封装好了之后
* 只给外部提供固定的操作方式
* 没接触的时候还以为非常的神秘
*/
public class MyStringStack {
private int maxNum; //该栈的大小
private char[] stackArray; //主要就是用这个字符数组来存放运算符
private int top; //栈顶元素的索引
public MyStringStack(int max){
maxNum = max;
stackArray = new char[maxNum];
top = -1;
}
public void push(char c){
stackArray[++top] = c;
}
public char pop(){
return stackArray[top--];
}
public boolean isEmpty(){
return top == -1;
}
}
上面的栈准备好后,下面的就是实现将中缀表达式转化为后缀表达式的代码了:
public class Change {
private MyStringStack mss; //用来转换的栈
private String start; //中缀表达式的字符串
private String result =""; //中缀表达式变为后缀表达式的结果
private boolean point_flag = false; //记录在一个数字中是否出现过小数点,防止多个小数点的出现
public Change(String start){
this.start = start;
mss = new MyStringStack(start.length());
}
/**
* 将中缀表达式中每个字符都取出来
* 判断不同的字符
* 并将其进行不同的处理
*/
public String doChange(){ //主要的转换函数
for(int i = 0;i < start.length();i++){
char c = start.charAt(i);
switch(c){
/**
* 这里是将加号和减号看作一种情况
* 这两个运算符的优先级相同
* 做出doDeal1的处理
*
* 至于result里面加上一个下划线
* 是为了在result里面分别前后为两个数字
* 就像是再上篇博客中用逗号来隔开是一样的道理
*
* point_flag用来标记是否出现了小数点
*/
case '+':
case '-':
result += '_';
point_flag = false;
doDeal1(c,1); //用来判别并处理是否弹出栈里的运算符
break;
case '*':
case '/':
result += '_';
point_flag = false;
doDeal1(c,2); //用来判别并处理是否弹出栈里的运算符
break;
/**
*根据规则
*遇到了左括号就直接push入符号栈
*/
case '(':
mss.push(c);
point_flag = false;
break;
/**
* 而遇到了右括号
* 需要做doDeal2的处理
*/
case ')':
doDeal2(); //括号的匹配问题
point_flag = false;
break;
case '~':
result = result + c;
break;
default:
if(c == '.'){
if(!point_flag){
point_flag = true;
result = result + c;
break;
}
else{
break;
}
}
else{
if(point_flag)
precision_count++;
result = result + c;
break;
}
}
}
/**
* 当中缀表达式读取完毕之后
* 需要再回过头来检查下符号栈
* 如果为空就没什么工作了
* 如果里面还有符号,则需要挨个弹出并写入后缀表达式中
*/
while(!mss.isEmpty())
result += mss.pop();
return result;
}
/**
* doDeal1操作
* 在遇到了加减乘除运算符的时候调用
* 传进来了一个参数i
* 用来标明优先级的大小的
* 加减的优先级大小为1
* 乘除的优先级大小为2
*
* 该函数做的工作就是检查符号栈是否为空
* 若为空,该符号直接入栈
* 否则就弹出栈顶元素
* 按照我们的规则来就好啦
*/
public void doDeal1(char c,int i){ //用来判别并处理是否弹出栈里的运算符
while(!mss.isEmpty()){
char topChar = mss.pop();
if(topChar == '('){
mss.push(topChar);
break;
}
else{
int j;
if(topChar == '+'||topChar == '-')
j = 1;
else
j = 2;
if(j < i){
mss.push(topChar);
break;
}
else
result += topChar;
}
}
mss.push(c);
}
/**
* doDeal2操作
* 遇到右括号后
* 也是按照规则办事~~~~~
* 你懂的
*/
public void doDeal2(){ //括号的匹配问题
while(!mss.isEmpty()){
char ch=mss.pop();
if(ch == '(')
break;
else
result = result + ch;
}
}
}
这样就好啦,两个类就解决了从中缀表达式转化到后缀表达式.今天就写到这里咯,很快就会给大家上怎么计算后缀表达式的代码咯,晚安~~~~~