Documentos de Académico
Documentos de Profesional
Documentos de Cultura
1
Msc. Lesbia Valerio Lacayo
La PILA y sus Utilidades
Se calcula empleando la notación polaca inversa utilizando una estructura de pila para los posibles valores. Las
expresiones pueden ser representadas en prefijo, infijo, postfijo.
La conversión de una forma de la expresión a otra forma necesita de una pila. Muchos compiladores utilizan una pila
para analizar la sintaxis de las expresiones, bloques de programa, etc. Antes de traducir el código de bajo nivel.
La mayoría de los lenguajes de programación son de contexto libre de los idiomas que les permite ser analizados con
máquinas basadas en la pila.
Por ejemplo, el cálculo: ((1 + 2) * 4) + 3, puede ser anotado como en notación postfija con la ventaja de no prevalecer
las normas y los paréntesis necesario:
12+4*3+
De la siguiente manera (la Pila se muestra después de que la operación se haya llevado a cabo):
1 Apilar operando 1
2 Apilar operando 1, 2
+ Añadir 3
4 Apilar operando 3, 4
* Multiplicar 12
3 Apilar operando 12, 3
+ Añadir 15
2
Msc. Lesbia Valerio Lacayo
Expresiones en notaciones infija, prefija y sufija
Cuando usted escribe una expresión aritmética como B * C, la forma de la expresión le proporciona información para que
pueda interpretarla correctamente. En este caso sabemos que la variable B está siendo multiplicada por la variable C, ya
que el operador de multiplicación * aparece entre ellos en la expresión. Este tipo de notación se conoce como infija ya
que el operador está entre los dos operandos sobre los que está actuando.
Considere otro ejemplo de notación infija, A + B * C. Los operadores + y * siguen apareciendo entre los operandos, pero
hay un problema. ¿Sobre qué operandos actúan? ¿Opera el + sobre A y B o el * opera sobre B y C? La expresión parece
ambigua.
De hecho, usted ha estado leyendo y escribiendo estos tipos de expresiones durante mucho tiempo y no le causan ningún
problema. La razón de esto es que usted sabe algo sobre los operadores + y *. Cada operador tiene un nivel de precedencia.
Los operadores de mayor precedencia se utilizan antes que los operadores de menor precedencia. Lo único que puede
cambiar ese orden es la presencia de paréntesis. El orden de precedencia para los operadores aritméticos ubica la
multiplicación y la división por encima de la suma y la resta. Si aparecen dos operadores de igual precedencia, se utiliza
un ordenamiento o asociatividad de izquierda a derecha.
Aunque todo esto puede ser obvio para usted, recuerde que las computadoras necesitan saber exactamente qué
operadores deben ejecutarse y en qué orden. Una forma de escribir una expresión que garantice que no habrá confusión
con respecto al orden de las operaciones es crear lo que se denomina expresión completamente agrupada.
Este tipo de expresión utiliza una pareja de paréntesis para cada operador. Los paréntesis dictan el orden de las
operaciones; no hay ambigüedad. Tampoco es necesario recordar las reglas de precedencia.
La expresión A + B * C + D se puede reescribir como ((A + (B * C)) + D) para mostrar que la multiplicación ocurre primero,
seguida por la adición que está más a la izquierda. A + B + C + D se puede escribir como ((A + B) + C) + D) ya que las
operaciones de adición se asocian de izquierda a derecha.
Hay otros dos formatos de expresión muy importantes que, al principio, pueden no parecer obvios. Considere la expresión
infija A + B. ¿Qué pasaría si moviéramos el operador antes de los dos operandos? La expresión resultante sería + A B.
Del mismo modo, podríamos mover el operador al final. Obtendríamos A B +. Estas expresiones se ven un poco extrañas.
Estos cambios en la posición del operador con respecto a los operandos crean dos nuevos formatos de expresión,
la notación prefija y la notación sufija (o postfija). La notación prefija requiere que todos los operadores precedan a
los dos operandos sobre los que actúan. La notación sufija, por otro lado, requiere que sus operadores aparezcan después
de los operandos correspondientes.
3
Msc. Lesbia Valerio Lacayo
A + B * C se escribiría como + A * B C en la notación prefija. El operador de multiplicación aparece inmediatamente antes
de los operandos B y C, denotando que el * tiene precedencia sobre el +. El operador de adición aparece entonces antes
de la A y del resultado de la multiplicación.
En notación sufija, la expresión sería A B C * +. Una vez más, el orden de las operaciones se conserva ya que el * aparece
inmediatamente después de la B y la C, denotando que el * tiene precedencia, con el + apareciendo después. Aunque los
operadores se movieron y ahora aparecen antes o después de sus respectivos operandos, el orden de cada operando se
mantuvo exactamente igual en relación con los demás.
Ahora considere la expresión infija (A + B) * C. Recuerde que en este caso, la notación infija requiere los paréntesis para
forzar que se lleve a cabo la adición antes de la multiplicación.
Sin embargo, cuando A + B fue escrito en notación prefija, el operador de adición fue movido simplemente antes de los
operandos, + A B. El resultado de esta operación se convierte en el primer operando para la multiplicación. El operador
de multiplicación se mueve delante de toda la expresión, dándonos * + A B C. Igualmente, en notación sufija A B + obliga
a que la adición ocurra primero. La multiplicación se puede hacer sobre ese resultado y el operando restante C. La
expresión sufija correcta es entonces A B + C *.
Considere nuevamente estas tres expresiones (ver la Tabla). Ha ocurrido algo muy importante. ¿A dónde se fueron los
paréntesis? ¿Por qué no los necesitamos en las notaciones prefija y sufija? La respuesta es que los operadores ya no son
ambiguos con respecto a los operandos sobre los que actúan. Solamente la notación infija requiere los símbolos adicionales.
El orden de las operaciones dentro de las expresiones prefijas y sufijas está completamente determinado por la posición
del operador y nada más. De muchas maneras, esto hace que la notación infija sea la notación menos deseable de usar.
(A + B) * C *+ABC AB+C*
La siguiente Tabla muestra algunos ejemplos adicionales de expresiones infijas y las expresiones equivalentes en
notaciones prefija y sufija. Asegúrese de entender cómo son equivalentes en términos del orden de las operaciones que
se están realizando.
(A + B) * (C + D) *+AB+CD AB+CD+*
4
Msc. Lesbia Valerio Lacayo
Conversión de expresiones infijas a notaciones prefija y sufija
Hasta el momento, hemos utilizado métodos ad hoc para convertir entre expresiones infijas y las expresiones
equivalentes en notaciones prefija y sufija. Como es de esperar, hay formas algorítmicas para realizar la conversión
que permiten transformar correctamente cualquier expresión de cualquier complejidad.
La primera técnica que vamos a considerar utiliza la noción de una expresión completamente agrupada que se discutió
anteriormente. Recordemos que A + B * C se puede escribir como (A + (B * C)) para mostrar explícitamente que la
multiplicación tiene precedencia sobre la adición. Sin embargo, al observar más de cerca, puede verse que cada pareja
de paréntesis también indica el comienzo y el final de un par de operandos con el operador correspondiente en la mitad.
Observe el paréntesis derecho en la subexpresión (B * C) anterior. Si tuviéramos que mover el símbolo de multiplicación
a esa posición y quitar el paréntesis izquierdo correspondiente, nos daría B C *, de hecho, habríamos convertido la
subexpresión a notación sufija. Si el operador de adición también es movido a la posición de su paréntesis derecho
correspondiente y se elimina el paréntesis izquierdo que le corresponde, se produciría la expresión sufija completa.
Si hacemos lo mismo, pero en lugar de mover el símbolo a la posición del paréntesis derecho, lo movemos a la izquierda,
obtenemos la notación prefija. La posición de la pareja de paréntesis es en realidad una pista sobre la posición final
del operador encerrado entre ellos.
Así que, para convertir una expresión, independientemente de su complejidad, ya sea a notación prefija o a notación
sufija, agrúpela completamente utilizando el orden de las operaciones. A continuación, mueva cada operador a la posición
correspondiente de los paréntesis izquierdo o derecho dependiendo de si desea obtener la expresión en notación prefija
o en notación sufija.
La siguiente es una expresión más compleja: (A + B) * C - (D - E) * (F + G). A continuación la conversión a las notaciones
sufija y prefija.
5
Msc. Lesbia Valerio Lacayo
Conversión general de notación infija a notación sufija
Necesitamos desarrollar un algoritmo para convertir cualquier expresión infija a una expresión sufija. Para hacer esto
vamos a examinar más de cerca el proceso de conversión.
Consideremos una vez más la expresión A + B * C. Como se muestra arriba, A B C * + es la equivalencia en notación sufija.
Ya hemos observado que los operandos A, B y C permanecen en sus posiciones relativas. Sólo los operadores cambian de
posición. Veamos de nuevo los operadores en la expresión infija. El primer operador que aparece de izquierda a derecha
es el +. Sin embargo, en la expresión sufija, el + está al final dado que el siguiente operador, *, tiene precedencia sobre
la adición. El orden de los operadores en la expresión original se invierte en la expresión sufija resultante.
A medida que procesamos la expresión, los operadores tienen que ser guardados en alguna parte, ya que sus operandos
derechos correspondientes no aparecen todavía. También, el orden de estos operadores guardados puede necesitar ser
invertido debido a su precedencia. Ése es el caso con la adición y la multiplicación en este ejemplo. Dado que el operador
de adición aparece antes del operador de multiplicación y tiene menor precedencia, necesita aparecer después de que se
use el operador de multiplicación. Debido a esta inversión del orden, tiene sentido considerar el uso de una pila para
almacenar a los operadores hasta que se necesiten.
Y ¿qué ocurrirá con (A + B) * C? Recuerde que A B + C * es la equivalencia en notación sufija. De nuevo, procesando esta
expresión infija de izquierda a derecha, vemos primero el +. En este caso, cuando vemos el *, el + ya se ha transcrito en
la expresión de resultado porque tiene precedencia sobre el * en virtud de los paréntesis. Ahora podemos empezar a ver
cómo funcionará el algoritmo de conversión. Cuando veamos un paréntesis izquierdo, lo guardaremos para indicar que habrá
otro operador de alta precedencia. Ese operador tendrá que esperar hasta que aparezca el paréntesis derecho
correspondiente para indicar su posición (recuerde la técnica de agrupar completamente). Cuando aparezca ese paréntesis
derecho, el operador puede ser extraído de la pila.
Al recorrer la expresión infija de izquierda a derecha, usaremos una pila para almacenar los operadores. Esto
proporcionará la inversión que hemos observado en el primer ejemplo. El tope de la pila siempre será el operador guardado
más recientemente. Siempre que leamos a un operador nuevo, tendremos que comparar la precedencia de ese operador
con la de los operadores que ya estén en la pila, si los hay.
Suponga que la expresión infija es una cadena de símbolos delimitados por espacios. Los símbolos de operaciones son *, /,
+ y -, junto con los paréntesis izquierdo y derecho, ( y ). Los símbolos de operandos son los identificadores de un solo
carácter A, B, C, y así sucesivamente. Los siguientes pasos producirán una cadena de símbolos en el orden sufijo.
1. Crear una pila vacía llamada pilaOperadores para almacenar los operadores. Crear una lista vacía para almacenar
la salida.
2. Convertir la cadena de entrada de notación infija a una lista, usando el método split.
3. Recorrer la lista de símbolos de izquierda a derecha:
o Si el símbolo es un operando, agregarlo al final de la lista de salida.
o Si el símbolo es un paréntesis izquierdo, enviarlo a pilaOperadores.
o Si el símbolo es un paréntesis derecho, extraer de pilaOperadores hasta que el correspondiente paréntesis
izquierdo se haya extraído. Agregar cada operador al final de la lista de salida.
o Si el símbolo es un operador *, /, +, ó -, incluirlo en pilaOperadores. No obstante, extraer previamente de la pila
los operadores que tengan mayor o igual precedencia y agregarlos a la lista de salida.
4. Cuando la expresión de entrada ha sido procesada completamente, verificar pilaOperadores. Todos los
operadores que aún estén almacenados en ella se deben enviar a la lista de salida.
6
Msc. Lesbia Valerio Lacayo
La Figura muestra el algoritmo de conversión trabajando sobre la expresión A * B + C * D. Observe que el primer operador
* se elimina al verse el operador +. Además, el + permanece en la pila cuando aparece el segundo *, ya que la multiplicación
tiene precedencia sobre la adición. Al final de la expresión infija, se extrae dos veces de la pila, eliminando ambos
operadores y colocando el + como el último operador en la expresión sufija.
7
Msc. Lesbia Valerio Lacayo
Evaluación de expresiones en notación sufija
Como ejemplo final sobre las pilas, consideraremos la evaluación de una expresión que ya está en notación sufija. En este
caso, una pila será de nuevo la estructura de datos elegida. Sin embargo, al recorrer la expresión sufija, son los operandos
los que deben esperar, no los operadores como en el algoritmo de conversión anterior. Otra forma de pensar en la solución
es que siempre que se vea un operador en la entrada, se usarán en la evaluación los dos operandos más recientes.
Para ver esto con más detalle, considere la expresión sufija 4 5 6 * +. Al recorrer la expresión de izquierda a derecha,
usted encuentra primero los operandos 4 y 5. En este punto, usted todavía no está seguro respecto a qué hacer con ellos
hasta que vea el siguiente símbolo. Ubicando cada uno en la pila asegura que estén disponibles si un operador viene a
continuación.
En este caso, el símbolo siguiente es otro operando. Así pues, como antes, inclúyalo en la pila y examine el símbolo siguiente.
Ahora vemos un operador, *. Esto significa que los dos operandos más recientes necesitan ser utilizados en una operación
de multiplicación. Al extraer dos veces de la pila, podemos obtener los operandos adecuados y luego realizar la
multiplicación (en este caso obtenemos 30 como resultado).
Ahora podemos manejar este resultado colocándolo de nuevo en la pila para que pueda ser utilizado como un operando para
los operadores posteriores en la expresión. Cuando se procesa el operador final, sólo quedará un valor en la pila.
Se extrae y se devuelve como el resultado de la expresión. La Figura muestra el contenido de la pila a medida que se
procesa toda la expresión de ejemplo.
La siguiente figura muestra un ejemplo un poco más complejo, 7 8 + 3 2 + /. Hay dos cosas a tener en cuenta en este
ejemplo. En primer lugar, el tamaño de la pila crece, disminuye y, a continuación, crece de nuevo a medida que las
subexpresiones se evalúan. En segundo lugar, la operación de división necesita ser manejada cuidadosamente. Recuerde
que los operandos en la expresión sufija están en su orden original ya que la notación sufija cambia sólo la ubicación de los
operadores.
Cuando los operandos para la división se extraen de la pila, estos se invierten. Dado que la división no es un operador
conmutativo, en otras palabras 15/515/5 no es lo mismo que 5/155/15, debemos estar seguros de que el orden de los
operandos no esté intercambiado.
8
Msc. Lesbia Valerio Lacayo
Un ejemplo más complejo de evaluación
Supongamos que la expresión sufija es una cadena de símbolos delimitados por espacios. Los operadores son *, /, + y -;
además, se supone que los operandos son valores enteros de un solo dígito. La salida será un resultado entero.
A continuación, algunas propuestas de algoritmos para evaluar y realizar conversiones de una expresión a sus
respectivas notaciones infija, prefija y postfija.
9
Msc. Lesbia Valerio Lacayo
Algoritmo de Evaluación de una expresión POSTFIJA
La conversión de cada una de las notaciones es sencilla, sin embargo hay que tomar en cuenta algunos aspectos,
entre ellos, el orden de precedencia y los limitadores (paréntesis, llaves o corchetes).
valid = true
while (mientras no se haya leído toda la cadena)
leer el siguiente símbolo de la cadena
si símbolo == ‘ ( ’ || símbolo == ‘ [ ’ || símbolo == ‘ { ’
push(PILA,simbolo);
si símbolo == ‘ ) ’ || símbolo == ‘ ] ’ || símbolo == ‘ } ’
si empty(PILA)
valid = false
else
i = pop( PILA )
si ( i no es equivalente del símbolo que abre )
valid = false
fin del while
si la pila no está vacía // No se verificaron todos los símbolos
valid = false, e imprimir cadena no válida
si valid = true
imprimir cadena válida
en caso contrario
imprimir cadena no válida
función_evalua_posfija{ 10
Msc.= Lesbia
tope -1; Valerio Lacayo
while (no sea el fin de la cadena){
El siguiente algoritmo evalúa de Notación Infija a Notación Postfija.
función_evalua_posfija{
tope = -1;
while (no sea el fin de la cadena){
simbolo = carácter de la cadena.
ifsimbolo es un operando
push(tope,simbolo);
else{ /* simbolo es un operador */
opnd2 = pop(tope);
opnd1 = pop(tope)
resultado=/*aplicar a simbolo opnd1 y opnd2*/
push(tope, resultado)
}
fin else
fin while
return(pop(tope));
}
TOPE = NULL;
while (no sea el fin de la cadena){
simbolo = carácter izquierdo de la cadena entrada;
if (simbolo es un operando)
cadenaposfija = cadenaposfija + símbolo;
else{
while (!empty(TOPE) &&prcd(pop(TOPE),símbolo)){
topsimbolo = pop(TOPE)
cadenaposfija = cadenaposfija + topsimbolo;
}//fin del while de precedencia
if (empty() || simbolo != ‘)’) push(simbolo);
else{
while ( (topsimbolo = pop(TOPE)) !=‘(’ ){
cadenaposfija = cadenaposfija+ topsimbolo;
}//fin del else
}//fin del else si no es operando
}//fin del while de la cadena
while (!empty(TOPE)){//extraer operadores restantes
topsimbolo = pop(TOPE)
cadenaposfija = cadenaposfija + topsimbolo;
}fin del while para extraer operadores
- Uso de paréntesis.
- Prioridad de operadores.
- El operador que aparece primero en la cadena es el que se aplica primero.
11
Msc. Lesbia Valerio Lacayo