Pilas

Anuncio
2.2. Stack (Pila LIFO)
Un stack es una estructura o conjunto de nodos en la cual puede insertarse o eliminarse sólo por uno
de los extremos, que es la cabeza.
Las operaciones que se pueden realizar en un stack son:
a. Agregar un elemento.
b.
elemento.
Figura 2.3 Ejemplo de un Stack secuencial.
Eliminar
un
Cada nodo que se va a
agregar o eliminar del stack
tiene una capacidad de C
bytes.
Algoritmos1 de agregar y eliminar un nodo en un stack secuencial.
ADDSTACKS(stack,top,base,max,dato)
SI stack = null TH stack,base=top
info.top <- dato
SN SI (top-base<max) TH top <- top + C
info.top <- dato
SN "el stack esta lleno"
FSI
FSI
FINADDSTACKS()
SUBSTACKS(stack,top,base,max,dato)
SI stack = null TH "no existe el stack"
SN SI (top >= base) TH info.top -> dato
top <- top - C
SI (top<base) TH stack,base,top=null
SN "el stack esta vacio"
FSI
FSI
FINSUBSTACKS()
Como puede darse cuenta el lector, no se ha perdido en ningún momento la información que existe en
algún nodo del stack
Ejemplo. Se cuenta con un stack secuencial, STACK1, se requiere determinar si algún nodo tiene la
información que esta en datox, si es así, debe cambiarse por la que hay en infox.
1
En los algoritmos de este documento existen errores, aunque se ha revisado cuidadosamente para que no
suceda, sin embargo, las continuas modificaciones conducen a que los cambios no se realicen en toda parte y, por
tanto algunos algoritmos quedan con una versión anterior. Los algoritmos se presentan en seudocódigo.
ALG()
// se considerara un stack adicional para guardar temporalmente la información
SI STACK1 = null TH "el stack no existe"
SN SI top1=base1 TH "el stack esta vacio"
SN w=0
MQ (top1 > base1 & w=0)
top1 <- top1 - C
SI info.top1=datox TH dato<-info.top1
info.top1<-infox
top1<-top1+C
w=1
SN
SI stack2=null TH stack2,base2,top2 FSI
info.top2 <- info.top1
top2 <- top2+C
FSI
FMQ
MQ (top2 > base2)
top2 <- top2 -C
info.top1 <- info.top2
top1 <- top1 + C
FMQ
FSI
FSI
FINALG()
26
Ejemplo. Se tiene un conjunto de stack secuenciales continuos, se ha llenado el stack i, hacer el
algoritmo para hacer los corrimientos necesarios a fin de dar espacio en el stack i.
Alg(G)
sum = lf-li
PARA j=1, n
top(j)=oldtop(j)
FPARA
inc = 0
PARA j = 1, n
sum = sum - [top(j) - base(j)]
FPARA
inc = |sum/n|
PARA i=1, n
oldtop(i) = oldtop(i) + inc
FPARA
PARA j=1, n
SI top(j)>oldtop(j) TH d(j) = top(j) - oldtop(j)
inc = inc + d(j)
SN d(j) = 0
FSI
FPARA
SI sum = 0 TH SATURA
SN alf = (k * (sum / c)) / n
bet = ((1 - k) * (sum/c)) / inc
nbase(1) = base (1)
PARA j = 2, n
Luis Carlos Torres Soler
Estructuras de Datos
nbase(j) = nbase(j-1) + [top(j-1) - base(j-1)] + alf*c + bet*c * d(j-1)]
27
FPARA
FSI
finalg()
Ejercicio
Sea que en el stack(i) se presento una condición de OVERFLOW al intentar insertar un nuevo
elemento, por lo tanto después de averiguar en que stack posterior (stack i+1,i+2, hay espacio
disponible, se empieza a desplazar hasta darle área al stack i. Puede buscarse en los stack i-1,i-2,..
Alg(M)
Adelan:
PARA l = i+1, n
SI top(l)-base(l+1)>K*C
TH PARA m=top(l)+C-1 a base(i+1)
info(m+c) = info(m)
FPARA
PARA m = i+1, l
base(m) = base(m) + c
top(m) = top(m) + c
FPARA
INSERTAR
FSI
FPARA
finadelan
Figura 2.5 Ejemplo de un stack encadenado.
Atras:
PARA l = i-1, 1
SI top(k) <base(k+1)
TH PARA m=base(l+1)+c, top(i)
info(m-c) = info(m)
FPARA
PARA m = l+1, i
base(m) = base(m)-c
top(m) = top(m) - c
FPARA
INSERTAR
FSI
FPARA
finatras
Facultad de Ingeniería
28
SATURADO
Fin_alg()
Figura 2.6 Agregar un nodo al Stack encadenado.
Cuando el stack es encadenado, cambia en
general
la
nomenclatura,
indicando
adecuadamente en que dirección se
encuentra la información.
Algoritmos de agregar y eliminar nodos en
un stack encadenado
ADDSTACKE(stack,dato)
Figura 2.7 Eliminar un nodo del Stack encadenado.
info.nodo <- dato
link.nodo <- null
SI stack = null TH stack <- nodo
SN link.nodo <- stack
stack <- nodo
FSI
FINADDSTACKE()
SUB STACKE(stack,dato)
SI stack = null TH "no existe el stack"
SN info.stack -> dato
stack <- link.stack
FSI
SUBSTACKE()
2.3. Cola (Pila FIFO)
Una cola es una estructura o conjunto de nodos en la cual puede insertarse solamente por la cola y
puede borrarse por la cabeza.
Figura 2.8. Ejemplo de una cola secuencial.
Las operaciones que se pueden realizar en una cola son:
a. Agregar un nodo.
b. Eliminar un nodo.
Luis Carlos Torres Soler
Estructuras de Datos
29
Algoritmos de agregar y eliminar un nodo en una cola secuencial.
ADDCOLAS(cola,col,cab,dato)
SI cola = null TH cola,col=cab
info.col <- dato
SN SI (cab-col < N) TH col <- col + C
info.col <- dato
SN "la cola esta llena"
FSI
FSI
FINADDCOLAS()
SUBCOLAS(cola,col,cab,dato)
SI cola = null TH "la cola no existe"
SN SI (cab-col > 0) TH info.cab -> dato
cab <- cab + C
cola <- cab
SI (cab < col) TH cola=null FSI
SN "la cola esta vacia"
FSI
FSI
FINSUBCOLAS()
En las colas encadenadas, la filosofía de las
secuenciales es la misma, se adiciona por el
fin (base, cola), se elimina por la cabeza. Sin
embargo, existe algún cambio de
Figura 2.9. Ejemplo de una Cola encadenada.
nomenclatura.
Las estructuras de listas se emplean mucho
en los sistemas de comunicación a partir de los computadores. Se involucran en la cola los procesos o
mensajes y se van atendiendo a medida como fueron llegando.
Figura 2.10. Agregar un nodo en una Cola encadenada.
Algoritmos de agregar y eliminar nodos en una cola encadenada
ADDCOLAE(cola,cab,dato)
info.nodo <- dato
link.nodo <- null
SI cola = null TH cola,cab <- nodo
SN link.cola <-nodo
cola <- nodo
FSI
FINADDCOLAE()
Similarmente se plantea el algoritmo de eliminación de nodos en una cola encadenada.
Facultad de Ingeniería
SUBCOLAE(cola,cab,dato)
SI cola = null TH "cola no existe"
SN info.cab -> dato
cab <- link.cab
SI cab = null TH cola = null FSI
FSI
FINSUBCOLAE()
30
Figura 2.11. Eliminar un nodo de una Cola encadenada.
La cola secuencial puede considerarse una área de memoria circular, en la cual cuando los N nodos se
llenan, es posible volver a iniciar en la cabeza (??).
Ejemplo. Se tiene una cadena circular que contiene la información de exponentes y coeficientes de un
polinomio en desorden, se requiere ordenarla.
NOTA. El nodo guía tiene coeficiente y exponente 0 (cero). Podría existir dos nodos con el mismo
exponente debido al desorden. Todos los exponentes son positivos. No existen nodos con coeficientes
cero.
INICIO()
// desarrollo utilizando la misma cadena para ello
SI POL = null TH ESCRIBA "la cadena no existe"
SN SI POL = link.POL TH ESCRIBA "la cadena esta vacia"
SN SI exp.POL ><0 TH ESCRIBA "el nodo guía no es el adecuado"
s <-- 1
MQ s >< 0
p <-- POL
q <-- link.p
r <-- link.q
MQ exp.q < exp.r
p <-- link.p
q <-- link.p
r <-- link.q
SI R = POL TH s <-- 0 FSI
FMQ
SI s = 1 TH SI exp.q = exp.r TH coef.q = coef.q+coef.r
SI coef.q = 0 TH link.p <-- link.r
SN link.q <-- link.r
FSI
FSI
SI coeg.q > coef.r TH aux <-- link.r
link.p <-- r
link.r <-- q
link.q <-- aux
FSI
Luis Carlos Torres Soler
Estructuras de Datos
s <-- 1
FSI
FMQ
ESCRIBA " polinomio ordenado "
FSI
FSI
FSI
FIN()
Ejemplo. El ejemplo anterior empleando otra cadena
ALG()
// ordenarla utilizando otra cadena.
SI POL = null TH ESCRIBA "la cadena no existe"
SN SI POL = link.POL TH ESCRIBA "la cadena esta vacia"
SN SI exp.POL ><0 TH ESCRIBA "el nodo guía no es el adecuado"
SN p <-- POL
q <-- link.p
BUSCAR_NODO()
exp.nodo <-- 0
coef.nodo <-- 0
q <-- dir.nodo
link.q <-- q
s <-- 0
MQ q >< POL
p1 <-- q
q1 <-- link.p1
SI s = 0 TH BUSCAR_NODO() FSI
exp.nodo <-- exp.q
coef.nodo <-- coef.q
s <-- 1
SI q1 = q TH link.p1 <-- dir.nodo
link.nodo <-- q1
s <-- 0
VAYA siga
FSI
MQ exp.q1 < exp.q
p1 <-- q1
q1 <-- link.p1
SI q1 = q TH link.p1 <-- dir.nodo
link.nodo <-- q1
s <-- 0
VAYA siga
FSI
FMQ
SI exp.q1 = exp.q TH coef.q1 <-- coef.q1 + coef.q
SN link.p1 <-- dir.nodo
link.nodo <-- q1
FSI
siga: p <-- link.p
q <-- link.p
FMQ
ESCRIBA " polinomio ordenado "
Facultad de Ingeniería
31
FSI
32
FSI
FSI
FIN()
Ejemplo. Insertar-borrar en una cola encadenada con un Stack de disponibles.
Alg()
Principal()
"teclee opción"
SI opción = I TH INSERTAR()
SN SI opción = B TH BORRAR()
SN "teclee opción correcta"
FSI
FSI
Fin_Principal()
INSERTAR()
SI Dispo = null TH ERROR Overflow
SN nodo <- Dispo
Dispo <- link.dispo
Info.nodo <- INFOR
link.nodo <- nodo
col <- nodo
FSI
FININSERTAR()
BORRAR()
SI col = null TH ERROR underflow
SN info.col -> INFOR
Q <- cab
cab <- link.cab
link.Q <- Dispo
Dispo <- Q
FSI
FINBORRAR()
2.4. Doble Cola (bicola)
Una doble cola es un conjunto de nodos en la cual la inserción o borrado puede realizarse por la
cabeza o por la cola. Igualmente, hay doble cola secuencial y encadenada.
Las operaciones que se pueden realizar en la doblecola son:
a. Agregar un nodo.
b. Eliminar un nodo.
Algoritmo de agregar un nodo en la cabeza.
Luis Carlos Torres Soler
Estructuras de Datos
33
Figura 2.12. Dobles colas: secuencial y encadenada.
ADDDCOLAS(cola,cab,dato)
SI cola = null TH cola=cab
info.cola <- dato
SN SI (cab-cola < N) TH cab <- cab - C
info.cab <- dato
SN "la doblecola esta llena"
FSI
FSI
FINADDDCOLAS()
Algoritmo de agregar un nodo en la cola.
ADDDCOLAS(cola,cab,dato)
SI cola = null TH cola=cab
info.cola <- dato
SN SI (cab-cola < N) TH cola <- cola + C
info.cola <- dato
SN "la doblecola esta llena"
FSI
FSI
FINADDDCOLAS()
2.5. Aplicaciones de Pilas
Todas las instrucciones de un lenguaje tienen dos cosas en común: operadores y operandos. Un
operando es una constante, un identificador (variable), o un label que se usa para realizar una
operación de bifurcación o identificación, un operador representa la acción u operación que se va a
realizar. 2
La gran mayoría de los lenguajes representan las expresiones aritméticas en la llamada forma INFIJA,
en la cual los operadores se encuentran entre los operandos. El proceso de compilar un programa
escrito en algún lenguaje de alto nivel requiere de guardar adecuadamente los operandos y operadores
para facilitar la evaluación de las operaciones, para ello, los compiladores emplean la notación
POSFIJA (o POLACA). En esta notación los operadores aparecen después de los operandos.
Ejercicio. Conteste en forma concreta lo siguiente:
2
Se ha dado un conjunto de ejemplos y ejercicios donde se muestran diferentes aplicaciones, pero aquí se
enuncian aplicaciones particulares.
Facultad de Ingeniería
a. ?Cuáles son dos diferencias y dos semejanzas entre una lista y una cola?.
34
b. ?Por qué en un Stack sólo puede trabajarse desde la cabeza?
c. ?Cuál es la razón para que la lectura en posorden de un árbol que representa una expresión
de asignación aritmética sea igual a la notación posfija de la misma expresión?
2.5.1. Notación Posfija
La notación posfija se usa para representar expresiones empleadas en un lenguaje de una forma que
especifica el orden de cálculo según los operadores.
1. Los operandos en la notación posfija van en el mismo orden de la notación infijo.
2. Los operadores en la notación posfija aparecen en el orden que deben calcularse.
3. Los operadores aparecen a continuación de sus operandos.
i) <operando> --> <identificador> | <operando><operando><operador>
ii) <operador> --> + | - | * | / | ^
El signo menos unario (y otros operadores unarios) se pueden representar por otro símbolo.
Ejemplo. @, %, &, etc., y se emplea:
iii) <operando> --> <operando>( @ | & | % )
Notación posfija en expresiones aritméticas.
Se utiliza una pila FIFO (cola) para la notación infija, otra para la notación posfija y un stack (pila
LIFO) para los operadores. Las siguientes reglas se utilizan para pasar una expresión aritmética en
infijo a una expresión en notación posfija.
1. Si el elemento que se lee de la expresión infija es una variable o constante (operando), se pasa
directamente a la pila que contiene la notación posfija.
2. Si el elemento que se lee de la expresión infija es un operador, se pasa al stack de operadores
desplazando antes de él para la pila de notación posfija todos los operadores de mayor o igual jerarquía
(prioridad).
NOTA. Se considera en todo lenguaje la siguiente tabla de prioridades:
Luis Carlos Torres Soler
(
paréntesis
-1
=
asignación
0
+, -
suma, resta
1
35
Estructuras de Datos
*, /
multiplicación,
división
2
^
potenciación
3
3. Si el elemento que se lee es un paréntesis abierto "(", pasa directamente al stack de operadores.
4. Si el elemento que se lee es un paréntesis cerrado ")", todos los operadores que están en el stack
hasta hallar un paréntesis abierto "(" pasan a la pila de la notación posfija, eliminando el paréntesis "(".
5. Si se ha terminado de leer la expresión los operadores que están en el stack pasan a la pila de la
notación posfija.
NOTA: no puede aparecer en la notación posfijo ningún paréntesis abierto.
Ejemplo. Sea la expresión X=(Y-(U+V/H)*S)+Y^A.
LEE
Facultad de Ingeniería
Pila de Notación Posfijo
Stack - operadores
X
X
=
X
=
(
X
=(
Y
XY
=(
-
XY
=(-
(
XY
=(-(
U
XYU
=(-(
+
XYU
=(-(+
V
XYUV
=(-(+
/
XYUV
=(-(+/
H
XYUVH
=(-(+/
)
XYUVH/+
=(-
*
XYUVH/+
=(-*
S
XYUVH/+S
=(-*
)
XYUVH/+S*-
=
+
XYUVH/+S*-
=+
36
LEE
Pila de Notación Posfijo
Stack - operadores
Y
XYUVH/+S*-Y
=+
^
XYUVH/+S*-Y
=+^
A
XYUVH/+S*-YA
=+^
@
XYUVH/+S*-YA^+=
2.5.2. Expresiones aritméticas en notación posfija
Igualmente se cumplen normas para la evaluación o cálculo de las expresiones una vez que se hallan
en notación posfija, se utiliza para ello un stack.
1.
Si el símbolo explorado es un operando (identificador o constante) ponerlo en la pila y
explorar el símbolo siguiente.
2.
Si el símbolo explorado es un operador unario, aplicarlo al operando superior de la pila y
sustituirlo por el resultado.
3.
Si el símbolo explorado es un operador binario, aplicarlo a los dos operandos superiores de la
pila y sustituirlos por el resultado.
Para la expresión X=(Y-(U+V/H)*S)+Y^A el proceso de evaluación para la notación posfija sería:
Lee
Stack de evaluación
X
Y
U
V
H
/
+
S
*
Y
A
^
+
=
X
XY
XYU
XYUV
XYUVH
X Y U (V/H)
X Y (U+(V/H))
X Y (U+(V/H)) S
X Y ((U+(V/H))*S)
X (Y-((U+(V/H))*S))
X (Y-((U+(V/H))*S)) Y
X (Y-((U+(V/H))*S)) Y A
X (Y-((U+(V/H))*S)) (Y^A)
X (Y-((U+(V/H))*S))+(Y^A)
(X=(Y-((U+(V/H))*S))+(Y^A))
Luis Carlos Torres Soler
Cada paréntesis indica una celda del
stack
Descargar