web-dev-qa-db-fra.com

Comment évaluer une expression infixe en une seule numérisation à l'aide de piles?

Je veux savoir s'il existe un moyen de résoudre des expressions d'infixe en une seule passe en utilisant 2 piles? Les piles peuvent être l'une pour l'opérateur et l'autre pour les opérandes ...

La manière standard de résoudre par un algorithme de shunt-yard est de convertir l'expression d'infixe en postfix (polissage inversé), puis de résoudre. Je ne veux pas convertir d'abord l'expression en suffixe.

Si l'expression est comme 2*3-(6+5)+8, comment résoudre?

44
nikoo28

Assez tard, mais voici la réponse.

Prenez deux piles:

  1. operator stack {pour les opérateurs et les parenthèses}.
  2. operand stack.

Algorithme

S'il existe un caractère à lire:

  1. Si le caractère est operand Appuyez sur operand stack, si le caractère est (, Appuyez sur le operator stack.
  2. Sinon si le caractère est operator
    1. Alors que le haut du operator stack n'est pas de moindre priorité que ce caractère.
    2. Pop operator de operator stack.
    3. Pop deux operands (op1 et op2) de operand stack.
    4. Le magasin op1 op op2 sur le operand stack retour à 2.1.
  3. Sinon si le caractère est ), faites la même chose que 2.2 - 2.4 jusqu'à ce que vous rencontriez (.

Sinon (plus de caractère à lire):

  • Opérateurs pop jusqu'à operator stack n'est pas vide.
  • Pop top 2 operands et Push op1 op op2 sur le operand stack.

renvoie la valeur supérieure de operand stack.

65
Rohit

La méthode indiquée dans le lien est vraiment bonne.

Permettez-moi de citer la source:

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.

J'espère que ça aide!

3
skrtbhtngr
  1. créer une pile d'opérateurs vide.
  2. créer une pile d'opérandes vide.
  3. pour chaque jeton dans la chaîne d'entrée
    une. obtenir le prochain jeton dans la chaîne d'infixe.
    b. si le suivant est un opérande, placez-le sur la pile d'opérandes.
    c. si le jeton suivant est un opérateur
    • Évaluez l'opérateur.
  4. tandis que la pile d'opérateurs n'est pas vide, pop opérateur et opérandes (gauche et droite), évaluez l'opérateur gauche à droite et poussez le résultat sur la pile d'opérandes.
  5. résultat pop de la pile d'opérateur.
1
nikhil

Ci-dessous, ma tentative d'évaluation de l'expression d'infixe en Java. S'il vous plaît faites le moi savoir si vous trouvez des bugs :)

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;
        }
    }
}
1
learner