14.05.2013 Views

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

SHOW MORE
SHOW LESS

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;

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!