package structure.week7;
import structure.week1.Stack;
// 使用表达式树来完成这个运算
public class InfixExpr {
String expr = null;
Element getElem = null;
public InfixExpr(String expr) {
this.expr = "0+"+expr; // 由于遇到优先级变化会生成单独节点,必须以最低优先级开头
getElem = new Element(expr);
}
public float evaluate() throws Exception{
Node root = createNode(null);
return (float) getValue(root);
}
public double evaluate_stack(){
return 0.0;
}
class Element{
private int index;
private String str;
public Element(String _str){
index = 0;
str = _str;
}
public double peekNextNum(){
int lastindex = index;
double resl = 0,resr=0;
int fbits = 0;
char ch = str.charAt(index);
boolean hasp = false;
while(ch=='.' || (ch<='9' && '0'<=ch)){
index += 1;
if(ch == '.') hasp = true;
else{
if(hasp){
fbits -= 1;
resr += (double)(ch-'0') * Math.pow(10,fbits);
}else{
resl *= 10;
resl += (ch-'0');
}
}
if(hasNext()) ch = str.charAt(index);
else break;
}
index = lastindex;
return resl+resr;
}
public double getNextNum() throws Exception{
if(!hasNext()) {
int a = index -2;
throw new Exception("表达式格式错误,在位置"+a+"处缺少操作数。");
}
double resl = 0,resr=0;
int fbits = 0;
char ch = str.charAt(index);
boolean hasp = false;
while(ch=='.' || (ch<='9' && '0'<=ch)){
index += 1;
if(ch == '.') hasp = true;
else{
if(hasp){
fbits -= 1;
resr += (double)(ch-'0') * Math.pow(10,fbits);
}else{
resl *= 10;
resl += (ch-'0');
}
}
if(hasNext()) ch = str.charAt(index);
else break;
}
return resl+resr;
}
public char peekNextOper(){
int lastindex = index;
char ch = '\0';
while(hasNext()){
ch = str.charAt(index);
index += 1;
if(ch=='+'||ch=='-'||ch=='*'||ch=='/') break;
ch = '\0';
}
index = lastindex;
return ch;
}
public char getNextOper(){
if(hasNext()){
char ch = str.charAt(index);
if((ch>='0' && '9'>=ch) || ch=='.') return '\0';
else{
index += 1;
return ch;
}
}else{
return '\0';
}
}
public boolean hasNext(){
return index<str.length();
}
}
class Node{
char op;
double val;
Node left,right;
Node(char o,double v){
left = null;
right = null;
op = o;
val =v;
}
}
private Node createNode(Node node) throws Exception{
if(getElem.peekNextOper() == '\0') return node;
if(node == null){
node = new Node('\0',getElem.getNextNum());
}
char ch = getElem.getNextOper();
Node root = new Node(ch,0);
root.left = node;
char chn = getElem.peekNextOper();
if(operUpDowm(ch,chn)<0){ // 操作符优先级提升
root.right = createNode(null);
}else if(operUpDowm(ch,chn)>0){ // 操作符优先级下降
root.right = new Node('\0',getElem.getNextNum());
return root; // 这里是遍历完一个连续乘除法,需要返回节点,考虑5-2*3-4,不返回会导致5-2*3+4
}else{
root.right = new Node('\0',getElem.getNextNum());
}
return createNode(root);
}
private int operUpDowm(char c1,char c2){
int temp1 = 0,temp2=0;
if(c1=='+'||c1=='-')temp1 = 0;
else if(c1=='*'||c1=='/')temp1 = 1;
if(c2=='+'||c2=='-')temp2 = 0;
else if(c2=='*'||c2=='/')temp2 = 1;
return temp1-temp2;
}
private double getValue(Node root) throws Exception{
if(root == null) throw new Exception("解析表达式出现异常");
switch(root.op){
case '+':
return getValue(root.left)+getValue(root.right);
case '-':
return getValue(root.left)-getValue(root.right);
case '*':
return getValue(root.left)*getValue(root.right);
case '/':
return getValue(root.left)/getValue(root.right);
case '\0':
return root.val;
default:
throw new Exception("目前还不支持 "+new StringBuilder().append(root.op).toString()+" 运算符。");
}
}
}