【问题标题】:How to evaluate an infix expression in just one scan using stacks?如何使用堆栈在一次扫描中评估中缀表达式?
【发布时间】:2012-11-05 11:07:50
【问题描述】:

我想知道是否有一种方法可以使用 2 个堆栈一次性解决中缀表达式? 堆栈可以一个用于运算符,另一个用于操作数...

分流码算法求解的标准方法是将中缀表达式转换为后缀(反向抛光)然后求解。我不想先将表达式转换为后缀。

如果表达式是2*3-(6+5)+8,如何解决?

【问题讨论】:

    标签: infix-notation stack


    【解决方案1】:

    很晚了,但这是答案。

    取两叠:

    1. operator stack { 用于运算符和括号}。
    2. operand stack.

    算法

    如果存在要读取的字符:

    1. 如果字符是operand,请按operand stack,如果字符是(,请按operator stack
    2. 否则,如果字符是operator
      1. 虽然operator stack 的顶部的优先级不低于此字符。
      2. operator stack 弹出operator
      3. operand stack 弹出两个operandsop1op2)。
      4. op1 op op2 存储在operand stack 返回到2.1。
    3. 否则,如果字符为),则与2.2 - 2.4 相同,直到遇到(

    Else(没有更多的字符可供阅读):

    • 弹出运算符直到operator stack 不为空。
    • operand stack 上弹出顶部 2 operandspush op1 op op2

    operand stack返回最高值。

    【讨论】:

    • "[和 2 一样,直到遇到 )" - 我相信应该有 '(' 而不是 ')'! (我算法中的这个错字引起了一些头痛!)
    • @EJP 从未听说过任何调车场算法。我自己提出了这个算法,可能是 dijkstra 甚至在我之前就提出了这个算法。否则我会这样做.. 与其先问我,然后在与我确认后才给它一个-1,我挑战你证明我不可能自己想出这个算法,并且这个文本被改编或复制从某处。在这种情况下,我很乐意进行必要的更改。谢谢
    • 哇,给个 -1 实在是太令人讨厌了。
    • @EJP Djikstra 是一位伟大的科学家,但我确实认为学生可以想出这个算法,特别是考虑到使用两个堆栈的线索。
    • 对于任何感兴趣的人,第 1 步应该是“1. 如果字符是操作数或 (。推送到堆栈:如果操作数推送到操作数堆栈上并且如果 ( 在操作符堆栈上。”
    【解决方案2】:

    the link中给出的方法确实不错。

    让我引用出处:

    We will use two stacks:
    
    Operand stack: to keep values (numbers)  and
    
    Operator stack: to keep operators (+, -, *, . and ^).  
    
    
    In the following, “process” means, (i) pop operand stack once (value1) (ii) pop operator stack once (operator) (iii) pop operand stack again (value2) (iv) compute value1 operator  value2 (v) push the value obtained in operand stack.          
    
    
    Algorithm:
    
    
    Until the end of the expression is reached, get one character and perform only one of the steps (a) through (f):
    
    (a) If the character is an operand, push it onto the operand stack.
    
    (b) If the character is an operator, and the operator stack is empty then push it onto the operator stack.
    
    (c) If the character is an operator and the operator stack is not empty, and the character's precedence is greater than the precedence of the stack top of operator stack, then push the character onto the operator stack.
    
    (d) If the character is "(", then push it onto operator stack.
    
    (e) If the character is ")", then "process" as explained above until the corresponding "(" is encountered in operator stack.  At this stage POP the operator stack and ignore "(."
    
    (f) If cases (a), (b), (c), (d) and (e) do not apply, then process as explained above.
    
    
    
     When there are no more input characters, keep processing until the operator stack becomes empty.  The values left in the operand stack is the final result of the expression.
    

    我希望这会有所帮助!

    【讨论】:

    • 好,除了在“处理”步骤中操作数的顺序被交换了——你先弹出操作数2,然后操作数1,然后计算操作数1操作数2...
    【解决方案3】:
    1. 创建一个空的运算符堆栈。
    2. 创建一个空的操作数堆栈。
    3. 对于输入字符串中的每个标记
      一种。获取中缀字符串中的下一个标记。
      湾。如果下一个是操作数,则将其放在操作数堆栈中。
      C。如果下一个标记是运算符
      • 评估操作员。
    4. 当运算符堆栈不为空时,弹出运算符和操作数(左和右),计算左运算符右并将结果压入操作数堆栈。
    5. 从运算符堆栈中弹出结果。

    【讨论】:

    • 这里没有提到运算符优先级。
    【解决方案4】:

    下面是我在 java 中的中缀表达式求值的尝试。如果您发现任何错误,请告诉我:)

    import java.util.*;
    
    public class ArithmeticExpressionEvaluation {
    
        public static void main(String[] args) {
            Scanner readExpression = new Scanner(System.in);
            System.out.print("Enter the expression: ");
            String expression = readExpression.nextLine();
            System.out.println(expression);
            System.out.println("Result: " + calculateExpression(expression));
        }
    
        public static long calculateExpression(String expression) {
    
            Stack<Long> operandStack = new Stack<>();
            Stack<Character> operatorStack = new Stack<>();
    
            if (!isValidExpression(expression)) {
                System.out.println("Not a valid expression to evaluate");
                return 0;
            }
    
            int i = 0;
            String currentInteger = null;
            while (i < expression.length()) {
    
                // System.out.println(expression.charAt(i));
                if (expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
    
                    currentInteger = expression.charAt(i) + "";
                    i++;
                    while (i != expression.length() && (expression.charAt(i) >= '0' && expression.charAt(i) <= '9')) {
                        currentInteger = currentInteger + expression.charAt(i);
                        i++;
                    }
    
                    operandStack.push(Long.parseLong(currentInteger));
                } else {
    
                    if (expression.charAt(i) == ')') {
    
                        while (operatorStack.peek() != '(') {
                            performArithmeticOperation(operandStack, operatorStack);
                        }
                        operatorStack.pop();
                    } else {
    
                        Character currentOperator = expression.charAt(i);
                        Character lastOperator = (operatorStack.isEmpty() ? null : operatorStack.peek());
    
    
                        if (lastOperator != null && checkPrecedence(currentOperator, lastOperator)) {
                            performArithmeticOperation(operandStack, operatorStack);
                        }
                        operatorStack.push(expression.charAt(i));
    
                    }
                    i++;
                }
    
            }
    
    
            while (!operatorStack.isEmpty()) {
                performArithmeticOperation(operandStack, operatorStack);
            }
    
        //    System.out.println(Arrays.toString(operandStack.toArray()));
        //    System.out.println(Arrays.toString(operatorStack.toArray()));
    
            return operandStack.pop();
    
        }
    
        public static void performArithmeticOperation(Stack<Long> operandStack, Stack<Character> operatorStack) {
            try {
                long value1 = operandStack.pop();
                long value2 = operandStack.pop();
                char operator = operatorStack.pop();
    
                long intermediateResult = arithmeticOperation(value1, value2, operator);
                operandStack.push(intermediateResult);
            } catch (EmptyStackException e) {
                System.out.println("Not a valid expression to evaluate");
                throw e;
            }
        }
    
    
        public static boolean checkPrecedence(Character operator1, Character operator2) {
    
            List<Character> precedenceList = new ArrayList<>();
            precedenceList.add('(');
            precedenceList.add(')');
            precedenceList.add('/');
            precedenceList.add('*');
            precedenceList.add('%');
            precedenceList.add('+');
            precedenceList.add('-');
    
    
            if(operator2 == '(' ){
                return false;
            }
    
            if (precedenceList.indexOf(operator1) > precedenceList.indexOf(operator2)) {
                return true;
            } else {
                return false;
            }
    
        }
    
        public static long arithmeticOperation(long value2, long value1, Character operator) {
    
            long result;
    
            switch (operator) {
    
                case '+':
                    result = value1 + value2;
                    break;
    
                case '-':
                    result = value1 - value2;
                    break;
    
                case '*':
                    result = value1 * value2;
                    break;
    
                case '/':
                    result = value1 / value2;
                    break;
    
                case '%':
                    result = value1 % value2;
                    break;
    
                default:
                    result = value1 + value2;
    
    
            }
            return result;
        }
    
    
        public static boolean isValidExpression(String expression) {
    
            if ((!Character.isDigit(expression.charAt(0)) && !(expression.charAt(0) == '('))
                    || (!Character.isDigit(expression.charAt(expression.length() - 1)) && !(expression.charAt(expression.length() - 1) == ')'))) {
                return false;
            }
    
            HashSet<Character> validCharactersSet = new HashSet<>();
            validCharactersSet.add('*');
            validCharactersSet.add('+');
            validCharactersSet.add('-');
            validCharactersSet.add('/');
            validCharactersSet.add('%');
            validCharactersSet.add('(');
            validCharactersSet.add(')');
    
            Stack<Character> validParenthesisCheck = new Stack<>();
    
            for (int i = 0; i < expression.length(); i++) {
    
                if (!Character.isDigit(expression.charAt(i)) && !validCharactersSet.contains(expression.charAt(i))) {
                    return false;
                }
    
                if (expression.charAt(i) == '(') {
                    validParenthesisCheck.push(expression.charAt(i));
                }
    
                if (expression.charAt(i) == ')') {
    
                    if (validParenthesisCheck.isEmpty()) {
                        return false;
                    }
                    validParenthesisCheck.pop();
                }
            }
    
            if (validParenthesisCheck.isEmpty()) {
                return true;
            } else {
                return false;
            }
        }
    }
    

    【讨论】:

    • 2+3(4*3) 给我的输出为 15。检查一次
    猜你喜欢
    • 2020-07-15
    • 2014-07-01
    • 1970-01-01
    • 2011-12-14
    • 2018-09-28
    • 2011-08-03
    • 2013-10-11
    • 2019-07-25
    相关资源
    最近更新 更多