Datos Punteros e Implementación Dinámica de Pilas
Datos Punteros e Implementación Dinámica de Pilas
Datos Punteros e Implementación Dinámica de Pilas
You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
<strong>Datos</strong> <strong>Punteros</strong> e <strong>Implementación</strong><br />
<strong>Dinámica</strong> <strong>de</strong> <strong>Pilas</strong><br />
Lección 8
Índice<br />
• 8.1 <strong>Datos</strong> puntero y datos dinámicos<br />
• 8.2 Estructuras <strong>de</strong> datos recursivas:<br />
representación mediante punteros y datos<br />
dinámicos<br />
• ADA: Tipos puntero y datos dinámicos<br />
• 8.3 Representación dinámica <strong>de</strong> una pila e<br />
implementación <strong>de</strong> operaciones
<strong>Datos</strong> puntero y datos dinámicos<br />
• Un puntero es un dato cuyo valor es la dirección<br />
en memoria <strong>de</strong> otro <strong>de</strong>terminado dato.<br />
p<br />
1467 1467 dato<br />
• El valor <strong>de</strong> p pue<strong>de</strong> verse como un apuntador<br />
(puntero) <strong>de</strong>l dato, gráficamente se representa<br />
así:<br />
p<br />
dato
• La dirección almacenada en un puntero va a<br />
ser transparente al programador. A éste sólo<br />
le interesa conocer el valor <strong>de</strong> un puntero<br />
como referencia a un <strong>de</strong>terminado dato.<br />
• Los punteros con los que vamos a trabajar<br />
están especializados para servir como<br />
referencia <strong>de</strong> datos <strong>de</strong> un <strong>de</strong>terminado tipo.<br />
• Nuestro lenguaje algorítmico estará dotado<br />
<strong>de</strong>l siguiente mecanismo constructor <strong>de</strong><br />
datos puntero:<br />
tipos tx = ...<br />
...<br />
tp_punt_a_tx = tx<br />
...<br />
variables p,q:tp_punt_a_tx
• Un puntero se pue<strong>de</strong> utilizar para servir <strong>de</strong> referencia<br />
<strong>de</strong> datos creados dinámicamente (es <strong>de</strong>cir, durante<br />
la ejecución <strong>de</strong>l algoritmo (*) ) mediante la instrucción:<br />
nuevoDato(p)<br />
que tiene como efecto la reserva <strong>de</strong> espacio para<br />
almacenar una nueva variable <strong>de</strong>l tipo apuntado por<br />
el puntero p, es <strong>de</strong>cir, <strong>de</strong>l tipo tx; esta variable queda<br />
apuntada por el puntero p:<br />
antes <strong>de</strong>spués<br />
p ?<br />
p dato<br />
creado<br />
(*) Se <strong>de</strong>nominan datos estáticos los almacenados en las variables<br />
<strong>de</strong>claradas al principio <strong>de</strong> los algoritmos (variables estáticas) y datos<br />
dinámicos los referenciados por un puntero (durante la ejecución <strong>de</strong>l<br />
algoritmo).
• Un dato creado dinámicamente no tiene ningún<br />
i<strong>de</strong>ntificador asociado como nombre. Se pue<strong>de</strong> hacer<br />
referencia a él a través <strong>de</strong> algún puntero, p, que<br />
apunte al dato, <strong>de</strong> acuerdo con la siguiente sintaxis:<br />
p<br />
que significa “dato apuntado por el puntero p”.<br />
p<br />
• A una variable <strong>de</strong> tipo puntero se le pue<strong>de</strong> asignar el<br />
valor <strong>de</strong> otra variable <strong>de</strong> tipo puntero (ambos <strong>de</strong>ben<br />
ser punteros <strong>de</strong> datos <strong>de</strong>l mismo tipo):<br />
q:=p<br />
p<br />
q<br />
p<br />
p<br />
q
• En este caso, el dato creado dinámicamente pue<strong>de</strong><br />
ser accedido <strong>de</strong> dos formas:<br />
p<br />
q<br />
• Existe un valor constante, nil, que <strong>de</strong>be ser<br />
asignado a todo puntero que se <strong>de</strong>see que no apunte<br />
a ningún dato. A cualquier variable <strong>de</strong> tipo puntero<br />
(in<strong>de</strong>pendientemente <strong>de</strong>l tipo <strong>de</strong>l dato al que apunte)<br />
pue<strong>de</strong> ser asignado dicho valor:<br />
p:=nil<br />
• La acción opuesta a nuevoDato es disponer:<br />
disponer(p)<br />
– Esta instrucción libera la zona <strong>de</strong> memoria que<br />
ocupaba el dato apuntado por el puntero p.<br />
• Finalmente, dos datos <strong>de</strong> tipo puntero (a datos <strong>de</strong>l<br />
mismo tipo) pue<strong>de</strong>n ser comparados con los<br />
operadores relacionales <strong>de</strong> igualdad (=) o<br />
<strong>de</strong>sigualdad ().
Estructuras <strong>de</strong> <strong>Datos</strong> Recursivas<br />
• Estructuras recursivas serían aquellas que en su<br />
<strong>de</strong>finición incluyesen un dato <strong>de</strong> su mismo tipo<br />
– Problema: cómo sabría el compilador o interprete<br />
cuánta memoria <strong>de</strong>be asignarle a una variable<br />
estática <strong>de</strong> ese tipo?
Estructuras <strong>de</strong> <strong>Datos</strong> Recursivas<br />
• Se <strong>de</strong>finen utilizando punteros a diferentes<br />
partes <strong>de</strong> la estructura<br />
– El tamaño y forma <strong>de</strong> la estructura podrá<br />
variar en ejecución (dinámica)
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
• Declaración <strong>de</strong> tipos<br />
OPCIÓN 1:<br />
type celda is<br />
record<br />
valor: integer;<br />
siguiente: enlace; -- enlace sin <strong>de</strong>finir<br />
end record;<br />
type enlace is access celda;<br />
OPCIÓN 2:<br />
type enlace is access celda;--celda sin <strong>de</strong>finir<br />
type celda is<br />
record<br />
valor: integer;<br />
siguiente: enlace;<br />
end record;<br />
En ADA, se <strong>de</strong>clara un tipo<br />
puntero para acce<strong>de</strong>r a datos<br />
<strong>de</strong> un <strong>de</strong>terminado tipo
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
• Declaración <strong>de</strong> tipos<br />
OPCIÓN CORRECTA (<strong>de</strong>claración circular):<br />
type celda; -- <strong>de</strong>claración parcial<br />
type enlace is access celda;<br />
-- <strong>de</strong>claración tipo punteros a celdas<br />
type celda is -- <strong>de</strong>claración completa <strong>de</strong> celda<br />
record<br />
valor: integer;<br />
siguiente: enlace;<br />
end record;
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
• Declaración <strong>de</strong> punteros y creación dinámica <strong>de</strong> datos<br />
type celda;<br />
type enlace is access celda;<br />
type celda is<br />
record<br />
valor:integer;<br />
siguiente:enlace;<br />
end record;<br />
e:enlace; -- equivale a e:enlace:=null;<br />
e:=new celda;<br />
e.valor:=13;<br />
e:=new celda'(13,null);<br />
e<br />
e<br />
•<br />
•<br />
e<br />
?<br />
null<br />
13<br />
null<br />
•<br />
En ADA, todo puntero no<br />
inicializado toma valor null<br />
Es válido asignar o<br />
comparar null para<br />
cualquier tipo <strong>de</strong> puntero<br />
e<br />
13<br />
null<br />
null
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
type celda;<br />
type enlace is access celda;<br />
type celda is<br />
record<br />
valor:integer;<br />
siguiente:enlace;<br />
end record;<br />
e:enlace; e null<br />
e:=new celda'(13,null);<br />
e:=new celda'(7,e);<br />
{<br />
•<br />
e<br />
1- Evaluación <strong>de</strong> la expresión<br />
7<br />
•<br />
2- Asignación <strong>de</strong>l valor<br />
•<br />
7<br />
•<br />
13<br />
null<br />
e<br />
e<br />
•<br />
•<br />
13<br />
null<br />
13<br />
null
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
• Asignación <strong>de</strong> punteros<br />
e,f:enlace;<br />
f:=new celda'(13,null);<br />
e:=f;<br />
f<br />
e<br />
•<br />
•<br />
f:=new celda'(13,null);<br />
e:=new celda;<br />
e.all:=f.all;<br />
e<br />
null<br />
f<br />
e<br />
13<br />
null<br />
•<br />
•<br />
f<br />
null<br />
f<br />
e<br />
f<br />
e<br />
•<br />
null<br />
13<br />
null<br />
13<br />
null<br />
•<br />
•<br />
13<br />
null<br />
13<br />
null<br />
?<br />
null
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
• Asignación a datos apuntados<br />
e,f:enlace;<br />
f:=new celda'(13,null);<br />
e:=new celda;<br />
e.all:=f.all;<br />
f<br />
e<br />
-- asignación entre los datos apuntados,<br />
-- no reserva espacio…<br />
•<br />
•<br />
13<br />
null<br />
13<br />
null<br />
-- e.valor:= 13; equivaldría a e.all.valor:=13;<br />
e<br />
f<br />
e<br />
null<br />
•<br />
•<br />
f<br />
null<br />
13<br />
null<br />
?<br />
null
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
• Comparación (entre tipos idénticos)<br />
e=f<br />
-- será cierto únicamente si ambos apuntan al<br />
-- mismo dato en memoria, o si ambos son null<br />
f<br />
e<br />
null<br />
null<br />
e.all=f.all<br />
-- será cierto únicamente si los datos a los que<br />
-- apuntan tienen los mismos contenidos<br />
f<br />
e<br />
•<br />
•<br />
•<br />
•<br />
13<br />
null<br />
13<br />
null<br />
13<br />
null<br />
e<br />
f<br />
f •<br />
13<br />
e •<br />
13<br />
52<br />
null
<strong>Punteros</strong> y <strong>Datos</strong> Dinámicos en Ada<br />
• Liberación <strong>de</strong> memoria <strong>de</strong> datos inaccesibles:<br />
– Debe hacerlo el programador<br />
with unchecked_<strong>de</strong>allocation;<br />
procedure disponer is new<br />
unchecked_<strong>de</strong>allocation(celda,enlace);<br />
e:enlace;<br />
...<br />
disponer(e);<br />
e •<br />
-- libera la memoria a la que apuntaba e,<br />
-- y <strong>de</strong>ja a e con valor null<br />
<br />
CUIDADO!!!<br />
e<br />
f<br />
•<br />
•<br />
13<br />
null<br />
e<br />
f<br />
null<br />
•<br />
e<br />
null<br />
13<br />
null
Representación <strong>Dinámica</strong> <strong>de</strong> Pila
Representación <strong>Dinámica</strong> <strong>de</strong> Pila<br />
• Representación por enca<strong>de</strong>namiento mediante<br />
punteros <strong>de</strong> los elementos <strong>de</strong> la pila<br />
– la pila será un puntero que apunta al elemento que<br />
está en la cima <strong>de</strong> la pila, y cada elemento apuntará<br />
al anterior<br />
– Ejemplos:<br />
• Pila con tres elementos<br />
• Pila vacía: p
Representación <strong>Dinámica</strong> <strong>de</strong> Pila<br />
• ESTATICA:<br />
• DINAMICA:
espec gpilas<br />
usa booleanos, naturales<br />
parametro formal<br />
genero elemto<br />
fpf<br />
genero pila<br />
operaciones<br />
VACIA: -> pila<br />
APILAR: pila elemto -> pila<br />
DESAPILAR: pila -> pila<br />
parcial CIMA: pila -> elemto<br />
VACIA?: pila -> bool<br />
ALTURA: pila -> nat<br />
dominios <strong>de</strong> <strong>de</strong>finicion p:pila; e:elemto<br />
CIMA(APILAR(p,e))<br />
ecuaciones p:pila, e:elemto<br />
DESAPILAR(VACIA) = VACIA<br />
DESAPILAR(APILAR(p,e)) = p<br />
CIMA(APILAR(p,e)) = e<br />
VACIA?(VACIA) = VERDAD<br />
VACIA?(APILAR(p,e)) = FALSO<br />
ALTURA(VACIA) = 0<br />
ALTURA(APILAR(p,e)) = SUC(ALTURA(p))<br />
fespec<br />
ALTURA Diferencia con los apuntes!!!!<br />
Estructura <strong>de</strong> datos diferente,<br />
operación <strong>de</strong> coste (1)
<strong>Implementación</strong> <strong>Dinámica</strong> <strong>de</strong> Pila<br />
• Características <strong>de</strong> la implementación:<br />
– En esta implementación, todas las operaciones <strong>de</strong> la<br />
especificación algebraica (VACIA, APILAR, DESAPILAR,<br />
CIMA, VACIA?, ALTURA) tienen tiempo <strong>de</strong> ejecución <strong>de</strong><br />
(1)<br />
– La pila pue<strong>de</strong> crecer hasta ocupar el máximo <strong>de</strong> la<br />
memoria (dinámica) disponible<br />
– Coste <strong>de</strong> memoria:<br />
• Coste “extra” para almacenar los punteros (enca<strong>de</strong>nar datos<br />
apilados)<br />
• Coste ajustado al necesario para almacenar los datos<br />
actuales <strong>de</strong> la pila<br />
– Aconsejable re<strong>de</strong>finir las operaciones <strong>de</strong> “:=“ y “=“<br />
– Se necesita una operación para liberar la memoria<br />
ocupada por una pila
generic<br />
type elemto is private;<br />
package gpilas is<br />
type pila is limited private;<br />
procedure crearVacia(p:out pila);<br />
--post: p=VACIA<br />
procedure apilar(p:in out pila; e:in elemto);<br />
--pre: p=p0<br />
--post: p=APILAR(p,e)<br />
procedure <strong>de</strong>sapilar(p:in out pila);<br />
--pre: (p=p0)<br />
--post: p=DESAPILAR(p0)<br />
….
function cima(p:in pila) return elemto;<br />
--pre: (p=p0) and (p0/=VACIA)<br />
--post: cima(p0)=CIMA(p0)<br />
function esVacia(p:in pila) return boolean;<br />
--post: esVacia(p)=VACIA?(p)<br />
function altura(p:in pila) return natural;<br />
--post: altura(p)=ALTURA(p)<br />
procedure asignar(pout:out pila; pin:in pila);<br />
--post: pout=pin, duplicando la representación en memoria<br />
function "="(p1,p2:in pila) return boolean;<br />
--post: p1=p2 si y solo si son iguales sus representaciones en<br />
-- memoria<br />
procedure liberar(p:in out pila);<br />
--post: p=VACIA, y a<strong>de</strong>más libera la memoria utilizada<br />
-- previamente por p<br />
….
…<br />
private<br />
type unDato;<br />
type ptDato is access unDato;<br />
type unDato is record<br />
dato:elemto;<br />
sig:ptDato;<br />
end record;<br />
type pila is record<br />
cim:ptDato;<br />
alt:natural;<br />
end record;<br />
end gpilas;<br />
ALTURA Diferencia con los apuntes!!!!<br />
Estructura <strong>de</strong> datos diferente,<br />
operación <strong>de</strong> coste (1)<br />
________ ANTES:________<br />
tipos<br />
pila=unDato;<br />
unDato= registro<br />
dato:elemento;<br />
sig: pila;<br />
freg;<br />
________AHORA:________<br />
tipos<br />
ptDato=unDato;<br />
unDato= registro<br />
dato:elemto;<br />
sig: ptDato;<br />
freg;<br />
pila= registro<br />
cim:ptDato;<br />
alt: natural;<br />
freg;
with unchecked_<strong>de</strong>allocation;<br />
package body gpilas is<br />
procedure disponer is new<br />
unchecked_<strong>de</strong>allocation(unDato,ptDato);<br />
procedure crearVacia(p:out pila) is<br />
begin<br />
p.cim:=null;<br />
p.alt:=0;<br />
end crearVacia;<br />
….
procedure apilar(p:in out pila; e:in elemto) is<br />
…?
procedure apilar(p:in out pila; e:in elemto) is<br />
aux:ptDato;<br />
begin<br />
aux:=p.cim;<br />
p.cim:=new unDato;<br />
p.cim.dato:=e;<br />
p.cim.sig:=aux;<br />
p.alt:=p.alt+1;<br />
end apilar;
procedure <strong>de</strong>sapilar(p:in out pila) is<br />
….?
procedure <strong>de</strong>sapilar(p:in out pila) is<br />
aux:ptDato;<br />
begin<br />
if p.cim/=null then<br />
aux:=p.cim;<br />
p.cim:=p.cim.sig;<br />
disponer(aux);<br />
p.alt:=p.alt-1;<br />
end if;<br />
end <strong>de</strong>sapilar;
function altura(p:in pila) return natural is<br />
begin<br />
….?<br />
end altura;<br />
function esVacia(p:in pila) return boolean is<br />
begin<br />
….?<br />
end esVacia;<br />
function cima(p:in pila) return elemto is<br />
begin<br />
….?<br />
end cima;
function altura(p:in pila) return natural is<br />
begin<br />
return p.alt;<br />
end altura;<br />
function esVacia(p:in pila) return boolean is<br />
begin<br />
return p.cim=null;<br />
end esVacia;<br />
function cima(p:in pila) return elemto is<br />
begin<br />
return p.cim.dato;<br />
end cima;
procedure liberar(p:in out pila) is<br />
…?
procedure liberar(p:in out pila) is<br />
aux:ptDato;<br />
begin<br />
aux:=p.cim;<br />
while aux/=null loop<br />
p.cim:=p.cim.sig;<br />
disponer(aux);<br />
aux:=p.cim;<br />
end loop;<br />
p.alt:=0;<br />
end liberar;
function "="(p1,p2:in pila) return boolean is<br />
…?
function "="(p1,p2:in pila) return boolean is<br />
pt1,pt2:ptDato;<br />
iguales:boolean:=true;<br />
begin<br />
if p1.alt/=p2.alt then<br />
return false;<br />
else<br />
pt1:=p1.cim;<br />
pt2:=p2.cim;<br />
while pt1/=null and iguales loop<br />
iguales:=pt1.dato=pt2.dato;<br />
pt1:=pt1.sig;<br />
pt2:=pt2.sig;<br />
end loop;<br />
return iguales;<br />
end if;<br />
end "=";
procedure asignar(pout:out pila; pin:in pila) is<br />
…?
procedure asignar(pout:out pila; pin:in pila) is<br />
ptout,ptin: ptDato;<br />
begin<br />
if esVacia(pin) then<br />
crearVacia(pout);<br />
else<br />
…..<br />
end if;<br />
end asignar;
… else<br />
ptin:=pin.cim;<br />
pout.cim:=new unDato;<br />
pout.cim.dato:=ptin.dato;<br />
ptout:=pout.cim;<br />
ptin:=ptin.sig;<br />
while ptin/=null loop<br />
ptout.sig:=new unDato;<br />
ptout:=ptout.sig;<br />
ptout.dato:=ptin.dato;<br />
ptin:=ptin.sig;<br />
end loop;<br />
ptout.sig:=null;<br />
pout.alt:=pin.alt;
procedure asignar(pout:out pila; pin:in pila) is<br />
ptout,ptin:ptDato;<br />
begin<br />
if esVacia(pin) then<br />
crearVacia(pout);<br />
else<br />
ptin:=pin.cim;<br />
pout.cim:=new unDato;<br />
pout.cim.dato:=ptin.dato;<br />
ptout:=pout.cim;<br />
ptin:=ptin.sig;<br />
while ptin/=null loop<br />
ptout.sig:=new unDato;<br />
ptout:=ptout.sig;<br />
ptout.dato:=ptin.dato;<br />
ptin:=ptin.sig;<br />
end loop;<br />
ptout.sig:=null;<br />
pout.alt:=pin.alt;<br />
end if;<br />
end asignar;