代码分为3部分,其实只要两部分的,就是一个测试类和一个计算类。下面看代码:
package lesson.arry;
import java.util.Stack;
public class Calculate {
public int calSuffix(String []str){ //计算后缀表达式的值
MyStack sk=new MyStack();
int second,first;
for(String tmp :str){
switch(tmp){
case "+":
second=sk.pop();
first=sk.pop();
sk.push(first+second);
break;
case "-":
second=sk.pop();
first=sk.pop();
sk.push(first-second);
break;
case "*":
second=sk.pop();
first=sk.pop();
sk.push(first*second);
break;
case "/":
second=sk.pop();
first=sk.pop();
sk.push(first/second);
break;
default:
Integer j=Integer.parseInt(tmp);
sk.push(j);
break;
}
}
return sk.pop();
}
public void infixToSuffix(String []source,String []destination){ //中缀表达式变换为后缀表达式
int index=0;
Stack<String> sk=new Stack<String>();
for(String tmp:source){
switch(tmp){
case "+":
case "-": //因为+ -它们的优先级是一样的,可以放一起处理
if(!sk.empty() && sk.peek()=="(") //只有左括号优先级比+号低 加号和减号优先级一样
sk.push(tmp);
else{
while(!sk.empty() && sk.peek()!="("){
destination[index++]=sk.pop();
}
sk.push(tmp);
}
break;
case "*":
case "/":
if(!sk.empty() && sk.peek()!="/" && sk.peek()!="*") //只有左括号优先级比+号低 加号和减号优先级一样
sk.push(tmp);
else{
while(!sk.empty() && (sk.peek()=="/" || sk.peek()=="*")){
destination[index++]=sk.pop();
}
sk.push(tmp);
}
break;
case "(": //所有的中括号还是大括号都可以换为小括号,所以没必要再去考虑其他复杂的括号
sk.push(tmp);
break;
case ")":
while(!sk.empty() && sk.peek()!="("){
destination[index++]=sk.pop();
}
sk.pop(); //去除左括号
break;
default:
destination[index++]=tmp;
break;
}
// for(String temp:sk) //测试用
// System.out.print(temp);
// System.out.println();
// for(String temp:destination)
// System.out.print(temp);
// System.out.println();
} //结束for循环
while(!sk.empty()){
destination[index++]=sk.pop();
}
}
public int calInfix(String[]str){ //计算中缀表达式
int count=0;
for(String temp:str){
if(temp.equals("(")){ //含有括号时后缀表达式要变短
count++;
}
}
String[]destination=new String[str.length-2*count];
infixToSuffix(str, destination);//中缀表达式变为后缀表达式
System.out.print("后缀表达式为:");
for(String temp:destination) //查看后缀表达式
System.out.print(temp);
System.out.println();
return calSuffix(destination); //调用后缀表达式
}
}
上面已经说了,只需要两个类的,为了更加的熟悉栈,所以自己写了一个栈,没java自带的好,勉强能用吧。代码如下:
package lesson.arry;
public class MyStack {
public int[] datas;
public int index=-1;
public MyStack(){
this(10); //必须放在最前面
}
public MyStack(int size){
datas=new int[size];
}
public void push(int data){
if(index>=datas.length-1){
int[] tempArry=new int[datas.length+5];
System.arraycopy(datas, 0, tempArry, 0, datas.length);
datas=tempArry;
// System.gc(); //通知垃圾回收器工作
}
index++;
datas[index]=data;
}
public int pop(){
if(index<=-1)
return 0;
return datas[index--];
}
public boolean isEmpty(){
return index<=-1;
}
public int peek(){
if(index<=-1)
return 0;
return datas[index];
}
/*
public static void main(String args[]){
MyStack ms=new MyStack();
Calculate ca=new Calculate();
// for(int i=0;i<30;i++){
// ms.push((int)(Math.random()*100+1));
// }
// while(!ms.isEmpty()){
// System.out.println(ms.pop());
// }
String []str=new String[]{"1","2","3","+","4","*","+"};
String []str2=new String[]{"1","+","(","2","+","3",")","*","4"};
try{
System.out.println(ca.calSuffix(str));
System.out.println(ca.calInfix(str2));
}catch(Exception e){
e.printStackTrace();
}
}
*/
}
两个类都定义完了,接下来就是随便写个类来测试一下:
package lesson.arry;
public class Test {
public static void main(String[] args) {
Calculate calculate = new Calculate();
String []str=new String[]{"1","2","3","+","4","*","+"};
String []str2=new String[]{"1","+",
"(","2","+","3",")","*","4"}; //1+(2+3)*4
String []str3=new String[]{"2","+","(","10","+","4","*","2",")",
"/","2","-","1"}; //2+(10+4*2)/2-1
try{
System.out.print("直接使用后缀表达式结果为: ");
System.out.println(calculate.calSuffix(str));
System.out.println(calculate.calInfix(str2)); //测试1
System.out.println(calculate.calInfix(str3)); //测试2
}catch(Exception e){
e.printStackTrace();
}
}
}
结果都是正确的,想验证的可以拷下去跑一跑,代码肯定有好多的bug,好多地方还没有考虑,比如输入字符要报错啊什么的,这个以后大家再改吧,现在只是简单的提供一下自己的算法,欢迎补充。