Cómo evaluar una expresión en notación de prefijo

evaluation expression-trees s-expression

Pregunta

Estoy tratando de evaluar una lista que representa una expresión en notación de prefijo. Aquí hay un ejemplo de tal lista:

[+, [sin, 3], [- 10 5]]

¿Cuál es la mejor manera de evaluar el valor de la lista?

Respuesta aceptada

Será más sencillo si usas postfix en lugar de prefijo. Ver notación polaca inversa (RPN) . Dada una expresión en RPN, es fácil evaluar eso usando solo una pila.

Pero como solicitó una forma de evaluar expresiones de prefijo sin recursión y usando pilas (para una forma posiblemente más simple, vea EDITAR: a continuación), aquí hay una manera:

Podemos hacer esto usando dos pilas.

Una pila (llámela Evaluación) contiene los operadores (como +, sin, etc.) y los operandos (como 3,4, etc.) y la otra pila (llámela Cuenta) tiene una tupla del número de operandos que quedan por ver + el número de los operandos que un operador espera.

Cada vez que ve a un operador, lo empuja en la pila de evaluación y empuja la tupla correspondiente en la pila de conteo.

Cada vez que vea un operando (como 3,5, etc.), verifique la tupla superior de la pila de recuento y disminuya el número de operandos que quedan por ver en esa tupla.

Si el número de operandos que quedan por ver se convierte en cero, se extrae la tupla de la pila de conteo. Luego, desde la pila de evaluación, saca el número de operandos requeridos (lo sabe debido al otro valor de la tupla), saque el operador y realice la operación para obtener un nuevo valor (u operando).

Ahora empuje el nuevo operando de nuevo en la pila de evaluación. Este nuevo empuje de operandos hace que veas otra vez la parte superior de la pila de Conde y haces lo mismo que acabamos de hacer (disminuir los operandos vistos, comparar con cero, etc.).

Si el recuento de operandos no se convierte en cero, continúe con el siguiente token en la entrada.

Por ejemplo, digamos que tuvo que evaluar + 3 + 4/20 4

Las pilas se verán como (la izquierda es la parte superior de la pila)

Count                  Evaluation                   Input
                                                   + 3 + 4 / 20 4

(2,2)                   +                            3 + 4 / 20 4

(2,1)                   3 +                            + 4 / 20 4

(2,2) (2,1)             + 3 +                            4 / 20 4

(2,1) (2,1)             4 + 3 +                            / 20 4

(2,2) (2,1) (2,1)       / 4 + 3 +                            20 4

(2,1) (2,1) (2,1)       20 / 4 + 3 +                            4

(2,0) (2,1) (2,1)       4 8 / 4 + 3 +                   

Since it has become zero, you pop off two operands, the operator / 
and evaluate and push back 5. You pop off (2,0) from the Count stack.

(2,1) (2,1)                5 4 + 3 +

Pushing back you decrement the current Count stack top.

(2,0) (2,1)               5 4 + 3 + 

Since it has become zero, you pop off 5,4 and + and evaluate and push back 9. 
Also pop off (2,0) from the count stack.

(2,0)                          9 3 + 

                               12

EDITAR:

Un amigo sugirió una manera de hacer esto sin múltiples pilas:

Comience desde el final, vaya al primer operador. Los tokens a la derecha de eso serán operandos. Evaluar y rehacer. Parece mucho más simple que hacerlo con dos pilas. Podemos usar una lista doblemente enlazada para representar la entrada que cambiamos durante el procesamiento. Cuando evalúa, elimina nodos y luego inserta el resultado. O quizás podrías usar una sola pila.


Respuesta popular

KISS, evalúa a la inversa como una expresión postfix.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow