用栈来实现表达式求值【Java版】

//String s="-3*(244+22/87/(2^3*57))";
String s="-3*  (-5  *  (-2)+23  4+22  /  87 /  (2^3*  57))"; //我测试负号,用这个,值跟上面的一样
求值System.out.println(evaluate(s));
//结果 -732.0016636418633



==========================

之前在百度搜了一个c语言版的,结果发现不是很能正常运行,看了几遍,实在是没看出为啥偶尔运行成功,偶尔运行不成功。。。于是自己动手,按照那思路写了版java的。。。


不过c和java版的差别蛮大的,
c语言字符串逐字处理,直接char *s指针后移s++就行了,java得用下标i去控制。。。
另外我是为了方便,直接用的现成的java.util.Stack,没有自己去构造栈。。。


=========================

代码如下:




import java.util.Stack;
/*
所使用的java内部类说明
java.util.Stack栈类,三个方法  push压栈, pop出栈, peek取栈顶的值
String类,方法 indexOf查子串位置(查不到返回-1),length串长度, charAt某位置的字符值, replaceAll字符串替换
StringBuffer类,可变字符串类,可以随时追加长度append,删除delete
 */
public class EvaluateExpression
{
public static void main(String[] args) 
{
//String s="-3*(244+22/87/(2^3*57))";
String s="-3*  (-5  *  (-2)+23  4+22  /  87 /  (2^3*  57))"; //我测试负号,用这个,值跟上面的一样
System.out.println(evaluate(s));
//结果 -732.0016636418633
}

public static double operate(double a,  char oper, double b) //计算函数Operate  
{  
   switch(oper) 
   {  
   case '+': return a+b;   
   case '-': return a-b;   
   case '*': return a*b;   
   case '/': return a/b;   
   case '^': return Math.pow(a,b);   
   default : return 0;   
   }   
}

public static boolean isOperators(char ch)
{
//若ch为运算符则返回true,否则返回false
return  "+-*/()#^".indexOf(ch) != -1;  //查找不到,表示不是运算符
}

public static char precede(char Aop, char Bop)
{
char prior[][] =  
{ // 运算符优先级表   
 // '+' '-' '*' '/' '(' ')' '#' '^'   
   {'>','>','<','<','<','>','>','<'},    /* '+' */
   {'>','>','<','<','<','>','>','<'},    /* '-' */
   {'>','>','>','>','<','>','>','<'},    /* '*' */
   {'>','>','>','>','<','>','>','<'},    /* '/' */
   {'<','<','<','<','<','=',' ','<'},    /* '(' */
   {'>','>','>','>',' ','>','>','>'},    /* ')' */
   {'<','<','<','<','<',' ','=','<'},    /* '#' */
   {'>','>','>','>','<','>','>','>'}     /* '^' */   
};   
int A_index="+-*/()#^".indexOf(Aop);
int B_index="+-*/()#^".indexOf(Bop);
return prior[A_index][B_index];
}


public static double evaluate(String myExpression)
{
myExpression=myExpression.replaceAll("\\s*", "");
//先去除字符串中所有空白
//System.out.println(myExpression);
Stack<Character> OPTR = new Stack<Character>();//运算符栈
Stack<Double> OPND = new Stack<Double>();//数据栈
OPTR.push('#');
StringBuffer tempdata=new StringBuffer();//临时操作数
int i=0;
int len=myExpression.length();

//增加负号处理。两种情况:如果表达式开头的-1 一定是负号;跟着左括号后的-是负号;,,其余是减号
//处理方式,在负号之前数据栈压入0,然后负号也就当减号处理了
if( myExpression.charAt(i)=='-' )
{ //目前i=0,判断首位是不是负号
OPND.push(0.0);  
OPTR.push('-');
i++;
}


//  while( i<len || OPTR.peek()!='#')
//{ // 两个条件在C语言可以合在一起,C的指针超出也没事,只不过值不对罢了。
   // 在Java没法合在一起,会数组下班越界报错。我这成2个whle循环了
while(i<len)

char c=myExpression.charAt(i);
       if (!isOperators(c))  
       {   
        tempdata.append(c);//字符串追加  
        i++;
           if (isOperators( myExpression.charAt(i) ))  
           {   
               double tmp=Double.parseDouble(tempdata.toString()); //字符串转换为数值的方法(double)   
               OPND.push(tmp);   
               tempdata.delete(0, tempdata.length());   //clear
           }   
       }   
       else //是运算符   
       {  
        if(c=='(' && myExpression.charAt(i+1)=='-')
        { //跟着左括号后的-是负号
        OPND.push(0.0);
        }
        char op=precede(OPTR.peek(), c);
        //System.out.println(OPTR.peek() + "   " + c  + "     比较关系 " + op);
           switch (op)  
           {  
           case '<': // 栈顶元素优先级低   
               OPTR.push(c);   
               i++;   
               break;   
           case '=': // 脱括号并接收下一字符   
               OPTR.pop();   
               i++;   
               break;   
           case '>': // 退栈并将运算结果入栈   
               char cop=OPTR.pop();   
               double b=OPND.pop();
               double a=OPND.pop();
               OPND.push(operate(a, cop, b));
               break;   
           } //switch  
       }  //if (!isOperators(c))  else  
}//while

while(OPTR.peek()!='#')
{
            char cop=OPTR.pop();   
            double b=OPND.pop();
            double a=OPND.pop();
            OPND.push(operate(a, cop, b));
}
return OPND.peek();   
}

}



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
表达式求值可以使用栈实现。具体步骤如下: 1. 创建一个操作数和一个操作符。 2. 遍历表达式中的每个字符,如果是操作数,则将其推入操作数中;如果是操作符,则将其推入操作符中。 3. 如果遇到左括号,则将其推入操作符中。 4. 如果遇到右括号,则取出操作符中的顶部元素进行计算,直到遇到左括号为止。每次计算后将结果推入操作数中。 5. 如果遇到操作符,先判断操作符顶的操作符优先级是否大于等于当前操作符的优先级,如果是,则取出操作符顶元素进行计算,并将结果推入操作数中,直到操作符顶的操作符优先级小于当前操作符的优先级,或者操作符为空为止。 6. 遍历完表达式后,如果操作符不为空,则取出操作符顶元素进行计算,并将结果推入操作数中,直到操作符为空。 7. 最终操作数中只剩下一个元素,即为表达式的值。 下面是使用 Java 代码实现: ```java import java.util.Stack; public class ExpressionEvaluation { public static int evaluate(String expression) { Stack<Integer> operandStack = new Stack<>(); Stack<Character> operatorStack = new Stack<>(); for (int i = 0; i < expression.length(); i++) { char ch = expression.charAt(i); if (ch == ' ') { // 忽略空格 continue; } else if (Character.isDigit(ch)) { // 如果是数字,将其入 int operand = 0; while (i < expression.length() && Character.isDigit(expression.charAt(i))) { operand = operand * 10 + expression.charAt(i) - '0'; i++; } i--; operandStack.push(operand); } else if (ch == '(') { // 如果是左括号,将其入 operatorStack.push(ch); } else if (ch == ')') { // 如果是右括号,计算括号内的表达式 while (operatorStack.peek() != '(') { int result = calculate(operatorStack.pop(), operandStack.pop(), operandStack.pop()); operandStack.push(result); } operatorStack.pop(); // 弹出左括号 } else if (isOperator(ch)) { // 如果是操作符 while (!operatorStack.isEmpty() && operatorStack.peek() != '(' && hasPriority(operatorStack.peek(), ch)) { int result = calculate(operatorStack.pop(), operandStack.pop(), operandStack.pop()); operandStack.push(result); } operatorStack.push(ch); } } while (!operatorStack.isEmpty()) { // 计算剩余的操作符 int result = calculate(operatorStack.pop(), operandStack.pop(), operandStack.pop()); operandStack.push(result); } return operandStack.pop(); // 返回最终结果 } private static boolean isOperator(char ch) { return ch == '+' || ch == '-' || ch == '*' || ch == '/'; } private static boolean hasPriority(char op1, char op2) { if (op1 == '*' || op1 == '/') { return true; } else if (op1 == '+' || op1 == '-') { return op2 == '+' || op2 == '-'; } else { return false; } } private static int calculate(char operator, int operand2, int operand1) { if (operator == '+') { return operand1 + operand2; } else if (operator == '-') { return operand1 - operand2; } else if (operator == '*') { return operand1 * operand2; } else { return operand1 / operand2; } } public static void main(String[] args) { String expression = "2 * (3 + 4) - 5 / 2"; int result = evaluate(expression); System.out.println(expression + " = " + result); } } ``` 输出结果为: ``` 2 * (3 + 4) - 5 / 2 = 11 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值