Вы находитесь на странице: 1из 9

Tema 10.

Punteros

Introduccin

Memoria de un ordenador Gestin del Heap Definicin Inicializacin y liberacin de memoria Operaciones bsicas El operador @ Listas con arrays Listas con punteros

Tema 10. Manejo Dinmico de Memoria. Punteros

Tipo de dato puntero


Procesamiento de listas

TDA Lista con punteros TDA Lista con Nodo Cabecera


2

Tema 10. Punteros

Introduccin

Memoria de un ordenador

Estructuras de datos dinmicas: el tamao no se conoce en tiempo de compilacin sino que ir aumentado o disminuyendo dinmicamente durante la ejecucin del programa Una estructura de datos dinmica es una coleccin de elementos llamados nodos (normalmente de tipo registro) que se enlazan o encadenan juntos El enlace se establece asociando con cada nodo un puntero que apunta al nodo siguiente de la estructura Existen varios tipos de estructuras dinmicas (listas enlazadas, grafos, rboles)

Nodo 1
Tema 10. Punteros

La memoria de un ordenador est dividida en casillas o celdas de igual tamao Para acceder a una casilla determinada hay que sealar su direccin, que identifica unvocamente a cada casilla Tanto en la memoria como en el procesador, la informacin es procesada y transmitida mediante unidades denominadas palabras de memoria La longitud de cada palabra de memoria vara de una mquina a otra, aunque hoy en da el tamao ms habitual es de 16, 32 y 64 bits.

Nodo 2

Nodo 3
3 Tema 10. Punteros 4

Divisin de la memoria principal


Zona de cdigo: es la parte de la memoria donde residen las instrucciones de nuestro programa; suele ocupar las direcciones ms bajas de la memoria Zona de datos: se alojan los datos estticos de nuestro programa, es decir, las variables globales del mismo. Suele ser un espacio de memoria limitado, por lo que el nmero y tamao de estas variables tambin est limitado. Forma junto con la Datos dinmicos zona de cdigo la parte esttica de la memoria La pila o stack, que suele encontrarse en las posiciones ms altas de memoria, creciendo dinmicamente hacia las direcciones ms bajas de la misma. En el stack se alojarn las variables locales de los diferentes mdulos conforme estos se van Datos estticos activando El heap, o zona de datos dinmicos, se encuentra entre la zona de datos estticos y la pila. Su tamao vara dependiendo de cmo vare el tamao de la pila, aunque por lo general los compiladores asignan como heap todo el espacio que no es zona de cdigo y de datos estticos. El programador no debe preocuparse de cmo se gestiona esta memoria, sino solo de su utilizacin ya que es el propio compilador el que se carga de ello
Tema 10. Punteros

Gestin del heap

Pila

Heap

Zona de datos Zona de cdigo

La memoria que ocupa el heap est dividida en bloques de diferentes tamaos Cuando desde el programa se solicita memoria para alojar un objeto de tamao n, el gestor del heap le asigna un bloque libre de tamao n, si lo hay, o de tamao t ( siendo t el valor ms pequeo del tamao de todos los bloques libres con tamao mayor que n). El bloque asignado se marca como ocupado y no puede ser asignado a otro objeto, por lo que se desperdicia un pequeo trozo de memoria Cuando se libera un objeto, el bloque de memoria que ocupaba pasa a ser libre, por lo que podr ser ocupado por otros objetos que lo soliciten
6

Tema 10. Punteros

El tipo de dato puntero


Un puntero es un objeto cuyo contenido es la direccin de memoria que ocupa otro objeto de nuestro programa El rango de valores vlidos ser el de las direcciones de memoria capaces de ser accedidas por el procesador del ordenador, ms una direccin de memoria especial, que se corresponde con el puntero nulo El puntero nulo recibe nombres diferentes dependiendo del lenguaje (Pascal NIL, C NULL) Declaracin de una variable tipo puntero Id_puntero:^tipo El ejemplo siguiente se lee como p apunta a la direccin de memoria donde se encuentra almacenado un entero p:^entero
7

Inicializacin y liberacin de memoria


Son dos operaciones importantes Para indicar al compilador que debe reservar espacio en el heap hay que inicializar el puntero con NEW(id_puntero) Al realizar la inicializacin, se asigna un bloque del heap en tiempo de ejecucin y se marca como ocupado El bloque permanece ocupado hasta que el programa libera explcitamente esa zona de memoria mediante la operacin DISPOSE(Id_puntero) Cuando un objeto apuntado no vaya a volver a utilizarse, ste debe liberarse. De esta manera, la memoria libre del heap aumenta, por lo que podr ocuparse por otros objetos. De otra forma, puede ocurrir que el heap se llene de bloques ocupados que no estn apuntados por ningn puntero, lo que supone un gravsimo desperdicio de memoria
8

Tema 10. Punteros

Tema 10. Punteros

Ejemplo
Var p:^integer;
Heap ? Datos Globales

Operaciones bsicas

New(p);
30 ? Heap Datos Globales

Acceso al contenido de los objetos apuntados por el puntero


Se utiliza el operador ^ (operador de indireccin o de desreferencia) Para acceder al contenido se usa Id_puntero^ Una vez que se accede al contenido se puede tratar con todas las operaciones vlidas para el tipo de datos apuntado por el puntero

New(p);
? Heap Datos Globales

P^:=50;
30 50 Heap Datos Globales

P^:=30;

30

Heap Datos Globales

Dispose(p);

30

Heap Datos Globales

p
Tema 10. Punteros

Asignacin de punteros (no est permitido asignar punteros que apunten a tipos de datos distintos) p:=q; Asignacin del contenido de los punteros p^:=q^; p^:=2300; Comparacin IF (p<>q) THEN IF (p=q) THEN Lectura y escritura: lgicamente, no se podrn realizar las operaciones de lectura y escritura de los punteros como tales. S que se podr leer o escribir el contenido de los objetos apuntados, siempre siguiendo las reglas de cada tipo concreto READLN(p^); WRITELN(q^); La constante NIL permite dar un valor a una variable puntero que no apunta a ninguna direccin. Puesto que NIL no apunta a ninguna posicin de memoria, cualquier referencia al contenido de la posicin que apunta un puntero NIL es ilegal p:=NIL; p^:=10; ERROR!
10

Tema 10. Punteros

Ejemplos
VAR q,p:^integer; BEGIN New(p); p^:=30; p^:=p^*10+50; New(q); q^:=p^; p^:=p^+q^; q:=p;
Tema 10. Punteros

Ejemplos
?

? ? ? ? ? 350 350 350

Var
q q q p p p^ p p^ q^ q^ q^ p p^ p p^ p p^ p^

Errores comunes

? 30 350 350 350 700 700

p:^integer; Begin NEW(p) p:=2300; NEW(p);

q q q

DISPOSE(p); p^:=2300;

{asignar a p la direccin 2300} {se reserva un nuevo bloque para p sin haber liberado el bloque antiguo} {intenta acceder al contenido del bloque que ya ha sido liberado}

p^

q^
11

p:=NIL IF (p^=0) THEN {intenta acceder al contenido de un puntero nulo} End;


Tema 10. Punteros

TYPE Empleado= RECORD Codigo:Integer; Nombre:string[30]; Edad:Integer; sueldo:real; END; VAR p p:^Empleado; BEGIN NEW(p); p^.codigo:=1001; P^.nombre:=Ana Garca; P^.edad:=35; P^.sueldo:=1754; DISPOSE(p); END;

p^ 1001 Ana Garca 35 1754

12

Algunas consideraciones

Ejemplo paso parmetros


PROGRAM Ejemplo_paso_parametros; TYPE Tptr=^integer; VAR p:Tptr; {--- ejemplo de paso por referencia--} PROCEDURE referencia(VAR q:Tptr); BEGIN New(q); q^:=20; END; {--- ejemplo de paso por valor ---} PROCEDURE valor(q:Tptr); BEGIN New(q); q^:=20; END;
Tema 10. Punteros

El puntero nulo

Se dice que tiene el valor NIL (o NULL) Antes de utilizar un puntero, debemos asegurarnos de que su valor no es NIL El gestor de memoria devuelve NIL cuando no ha sido posible la asignacin de memoria requerida por la llamada NEW A la hora de pasar como parmetro un puntero, debe realizarse por referencia, siempre y cuando lo que se haga dentro del mdulo llamado afecte no al objeto apuntado por el puntero, sino al propio puntero En cambio, si lo que realizamos en el interior del mdulo llamado afecta no ya al puntero sino al objeto apuntado por el mismo, entonces es indiferente el modo de pasar el parmetro ya que ambos punteros - el puntero existente en memoria principal y el creado en la pila - apuntan al mismo espacio de memoria

Paso de parmetros

{-- programa principal ------} BEGIN referencia(p); writeln(p^); Dispose(p); valor(p); writeln(p^); END.

Tema 10. Punteros

13

14

El operador @

Procesamiento de listas

El operador @ se puede aplicar a una variable (no puntero) y devuelve la direccin de memoria dnde est alojada dicha variable p := @v En este caso, no se est trabajando con memoria dinmica, sino con memoria esttica, y el puntero no va a apuntar a direcciones del heap sino a direcciones del rango de la zona de datos estticos Ejemplo
Var Begin v:=10; p:=@v; p^:=p^+1; writeln(v,p^); End. p:^integer; v:integer;

Operaciones bsicas sobre listas


Mostrar los elementos de la lista Insertar un elemento Borrar un elemento Buscar un elemento Pilas o listas LIFO (Last In First Out)

Tipos especiales de listas

Las inserciones siempre se realizan por el final Las eliminaciones siempre se realizan por el final La inserciones siempre se realizan por el final Las eliminaciones siempre se realizan por el principio
16

Colas o listas FIFO (First In First Out)


Tema 10. Punteros

15

Tema 10. Punteros

Listas con arrays

Insertar un elemento
PROCEDIMIENTO insetar( VAR lista:LISTAENTEROS; VAR NumElem:ENTERO; elem:ENTERO; pos:ENTERO ) {lista de enteros} {N de elementos de la lista} {elemento a insertar} {posicin en la que se inserta}

Se utiliza un array unidimensional para almacenar la lista, de manera que el i-simo elemento de la lista se corresponde con el i-simo elemento del array
TIPO listaenteros=ARRAY[1..Limite] de ENTEROS VARIABLES lista:listaenteros

Operaciones inmediatas

Leer y escribir los elementos de la lista Buscar un elemento de la lista Los arrays deben tener una longitud fija (son estructuras estticas) Operacin de insercin y eliminacin (algoritmos sencillos pero ineficientes)
17

Limitaciones

VARIABLES i:ENTERO INICIO PARA i=0 HASTA NumElem-pos HACER lista[NumElem+1-i] lista[NumElem-i] {Desplazar todos los elementos a partir de} FIN_PARA {la posicin en la que se va a insertar} Lista[pos] elem {Insertar el elemento en la posicin pos} NumElem NumElem+1 {Incrementar el n total de elementos} FIN_PROC Lista es (34,52,12,6,10) y NumElem es 6 Llamada al procedimiento INSERTAR(lista,NumElem,38,3) 34,52,12 ,6 ,10 34,52,38,12,6,10

Tema 10. Punteros

Tema 10. Punteros

18

Listas enlazadas

Lista enlazada
BOA GATO PERRO LEON
Direccin 150 151 152 153 154 155 BOA PERRO 157 NIL LEON 153

Cundo usar estructuras dinmicas


El tamao de una lista no se puede predecir a priori Las operaciones de insercin y borrado son frecuentes

Las listas enlazadas son una secuencia de nodos que se enlazan mediante un enlace o puntero Cada nodo o elemento de la lista debe tener dos campos:

Un campo con los valores de cada elemento (datos) Un campo que indica la posicin del elemento siguiente (enlace o puntero, representado por una flecha)
8 Lista 5 8 1 9 8 1 9 3 8 Lista de enteros con arrays

156 157 158 19 Tema 10. Punteros 20 GATO 150

Lista enlazada de enteros con punteros


Tema 10. Punteros

Implementacin de listas

Lista de enteros con punteros


TYPE
TipoElemento=Integer; PunteroNodo=^TipoNodo; TipoNodo= record Elemento:TipoElemento; Siguiente:PunteroNodo; End; Lista=PunteroNodo;

Declaracin de un nodo TYPE


TipoElemento=; {puede ser cualquier tipo de datos} PunteroNodo=^TipoNodo; TipoNodo = record Elemento:TipoElemento; Siguiente:PunteroNodo; End;

TipoElemento puede ser cualquier tipo de datos vlido La declaracin de PunteroNodo precede a TipoNodo: sta es la nica situacin en la que se permite utilizar un identificador antes de ser definido Cuando se implementa una lista enlazada se necesita un puntero adicional (puntero cabecera) que se utiliza para apuntar al primer elemento de la lista El puntero cabecera es distinto a los elementos de la lista puesto que no contiene ningn elemento sino solo un dato de tipo puntero, sirve simplemente para obtener el principio de la lista por lo que se trata de un putero externo que est fuera de la lista y que debe existir siempre La declaracin sera de la siguiente manera VAR cabecera: PunteroNodo; Si el valor de cabecera es NIL significa que la lista est vaca
21

VAR
L:Lista; P:PunteroNodo; X:TipoElemento;
Tema 10. Punteros

{---- Cabecera de la lista -----} {----- Nodo individual ---------}

Tema 10. Punteros

22

Crear una lista a partir de datos de entrada


PROCEDURE crea_lista5_teclado(VAR l:lista); VAR i:INTEGER; x:TipoElemento; p:PunteroNodo; BEGIN WRITELN('Introduzca 5 datos de entrada para crear la lista'); NEW(l); READLN(x); l^.elemento:=x; p:=l; i:=2; WHILE (i<=5) DO BEGIN READLN(x); NEW(p^.siguiente); p:=p^.siguiente; p^.elemento:=x; i:=i+1; END; p^.siguiente:=NIL; END;
Tema 10. Punteros 23

Crear una lista a partir de los datos de un fichero


PROCEDURE crea_lista_fichero(VAR l:lista;VAR F:FIC); {Se supone que el fichero ya est creado y asignado. El tipo FIC se defini en el programa principal} VAR i:INTEGER; x:TipoElemento; p:PunteroNodo; BEGIN RESET(F); IF NOT EOF(F) THEN BEGIN READ(F,x); NEW(l); l^.elemento:=x; p:=l; WHILE NOT EOF(F) DO BEGIN READ(F,x); NEW(p^.siguiente); p:=p^.siguiente; p^.elemento:=x; END; p^.siguiente:=NIL; END ELSE WRITELN(El fichero est vaco. No se puede crear la lista); CLOSE(F); END;

Tema 10. Punteros

24

Imprimir una lista


PROCEDURE imprime_lista(l:lista); VAR p:PunteroNodo; BEGIN p:=l; WHILE (p<>NIL) DO BEGIN WRITELN(p^.elemento); p:=p^.siguiente; END; END;
Tema 10. Punteros 25

Aadir un elemento al final de la lista


PROCEDURE add_elemento(VAR l:lista;x:TipoElemento); VAR p:PunteroNodo; BEGIN IF (l=NIL) THEN BEGIN NEW(l); l^.elemento:=x; l^.siguiente:=NIL; END ELSE BEGIN p:=l; WHILE (p^.siguiente<>NIL) DO p:=p^.siguiente; NEW(p^.siguiente); p:=p^.siguiente; p^.elemento:=x; p^.siguiente:=NIL; END; END;
Tema 10. Punteros 26

Borrar un elemento del final


PROCEDURE borra_ultimo(VAR l:lista); VAR p:PunteroNodo; BEGIN IF (l=NIL) THEN WRITELN('Error.Lista vaca. No se puede borrar') ELSE BEGIN p:=l; IF (p^.siguiente=NIL) THEN BEGIN l:=NIL; DISPOSE(p); END ELSE BEGIN WHILE (p^.siguiente^.siguiente<>NIL) DO p:=p^.siguiente; DISPOSE(p^.siguiente); p^.siguiente:=NIL; END; END; END;

Insertar un elemento en una lista ordenada


PROCEDURE inserta_elem(VAR l:lista;x:TipoElemento); VAR p,q:PunteroNodo; encontrado:boolean; BEGIN new(q); q^.elemento:=x; IF (l=NIL) THEN BEGIN l:=q; q^.siguiente:=NIL; END ELSE BEGIN p:=l; IF (q^.elemento<p^.elemento) THEN BEGIN q^.siguiente:=p; l:=q; END ELSE BEGIN

{-- la lista est vaca --}

{-- al menos hay un elemento --} {-- se inserta en 1 posicin -}

{-- se inserta a partir de la 2 posicin--}

********* segmento de cdigo en la siguiente diapositiva *********** END; END; (--- fin de cuando hay al menos un elemento ----} END;
27 Tema 10. Punteros 28

Tema 10. Punteros

IF (p^.siguiente<>NIL) THEN BEGIN {- si hay 2 elementos o mas } encontrado:=FALSE; WHILE (p^.siguiente^.siguiente<>NIL) AND NOT encontrado DO BEGIN {mientras no se llegue al penltimo} IF (p^.siguiente^.elemento<q^.elemento) THEN { y no se haya encontrado dnde insertar} p:=p^.siguiente ELSE BEGIN q^.siguiente:=p^.siguiente; p^.siguiente:=q; encontrado:=TRUE; END; END; {---- Fin del while no llegue al penltimo y no hay encontrado dnde insertar----} IF NOT encontrado THEN BEGIN {-- insertar como ltimo o penltimo ---} IF (q^.elemento<p^.siguiente^.elemento) THEN BEGIN {insertar como penltimo } q^.siguiente:=p^.siguiente; p^.siguiente:=q; END ELSE BEGIN {insertar como ltimo} q^.siguiente:=NIL; p^.siguiente^.siguiente:=q; END; END; END {----- fin del SI hay 2 o mas elementos ----} ELSE BEGIN {- hay solo un elemento. se inserta el 2 como ltimo elemento --} p^.siguiente:=q; q^.siguiente:=NIL; END;
Tema 10. Punteros 29

Insertar un elemento en una lista ordenada

TDA Lista con Punteros

Tipo de Dato Abstracto


Definir el tipo de dato Definir todas las operaciones (primitivas) que se van a utilizar sobre ese tipo de dato

TDA Lista de enteros: Definicin de tipo TYPE


TipoElemento=Integer; PunteroNodo=^TipoNodo TipoNodo= record Elemento:TipoElemento; Siguiente:PunteroNodo; End; Lista=PunteroNodo;

VAR

L:Lista {---- Cabecera de la lista -----} P:PunteroNodo; {----- Nodo individual ---------}
30

Tema 10. Punteros

Primitivas con el TDA Lista con Punteros

Implementacin de primitivas (Crear lista y Comprobar si vaca)


PROCEDURE crear ( VAR l: lista ); { Crea la lista vaca } BEGIN { Del procedimiento hacerNula } l:= NIL; {Establece como ltimo elemento de la lista la cabecera } END; { Del procedimiento hacerNula } { ---------------------------------------------------- } FUNCTION vacia ( l: lista ) : BOOLEAN; { Devuelve True si la lista l est vaca, o FALSE en otro caso } BEGIN { De la funcin vaca } vacia := l = NIL; END; { De la funcin vaca }

Operaciones de la lista enlazada


Crear lista vaca Comprobar si la lista est vaca Localizar la posicin Recuperar elemento de una posicin Insertar elemento Borrar elemento

Tema 10. Punteros

31

Tema 10. Punteros

32

Localizar un elemento
FUNCTION localizar ( x : TipoElemento ; l : lista ) : PunteroNodo ; { Devuelve la posicin en que se encuentra el elemento x en la lista l } VAR p : PunteroNodo; encontrado : boolean; BEGIN { De la funcin localiza } p := l; encontrado := FALSE; WHILE ( (p <> NIL ) AND ( NOT encontrado )) DO IF ( p^.elemento = x ) THEN encontrado := TRUE ELSE p := p^.siguiente; localiza := p; END; { De la funcin localiza }

Recuperar un elemento
PROCEDURE recuperar ( VAR x: TipoElemento; p: PunteroNodo; l: lista ); { Recupera en x el elemento que ocupa la posicin p de la lista l } BEGIN { Del procedimiento recupera } IF (p<>NIL) THEN { No estamos al final de la lista } x:= p^.elemento ELSE WRITELN ( posicion errnea ); END; { Del procedimiento recupera }

Tema 10. Punteros

33

Tema 10. Punteros

34

Insertar un elemento
PROCEDURE insertar ( x: TipoElemento ; p :PunteroNodo; VAR l : lista ); { Inserta el elemento x en la posicion p de la lista l , si p es una posicin vlida } VAR q,aux : PunteroNodo; BEGIN { Del procedimiento insertar } IF (l=NIL) THEN BEGIN {Lista est vaca, se insertar el primer elemento} NEW(l); l^.elemento:=x; l^.siguiente:=NIL; END ELSE BEGIN NEW(aux); aux^.elemento:=x; IF (l=p) THEN BEGIN {se inserta como el primero de la lista} l:=aux; l^.siguiente:=p; END ELSE BEGIN {se inserta en cualquier otra posicin} q:=l; {q apuntar al anterior de p} WHILE (q^.siguiente<>p) DO q:=q^.siguiente; q^.siguiente := aux; aux^.siguiente:=p; END; END; END; { Del procedimiento insertar }
Tema 10. Punteros 35

Borrar un elemento
PROCEDURE borrar ( p : PunteroNodo ; VAR l: lista ); { Borra el elemento que ocupa la posicin p de la lista l, si p es una posicin vlida} VAR q : PunteroNodo; BEGIN { Del procedimiento borrar } IF (l=NIL) THEN {lista vaca} WRITELN (Error. No se puede borrar. Lista vaca) ELSE IF (l=p) THEN BEGIN {borrar el primero de la lista} l:=l^.siguiente; DISPOSE(p); END ELSE BEGIN {borra cualquier otro elemento} q:=l; WHILE (q^.siguiente<>p) AND (q^.siguiente<>NIL) DO q := q^.siguiente; IF (q^.siguiente<>NIL) THEN BEGIN q^.siguiente:=q^.siguiente^.siguiente; DISPOSE ( p ); END ELSE WRITLEN(Error. No se encuentra la posicin); END; END; END; { Del procedimiento borrar }
Tema 10. Punteros 36

Primitivas adicionales

Posicin anterior a una dada


FUNCTION anterior ( p: PunteroNodo; l : lista ) : PunteroNodo; { Devuelve la posicion anterior a la posicion p en la lista l. Si p no es una posicin vlida o estamos al principio de la lista devuelve NIL } VAR aux: PunteroNodo; encontrado: boolean; BEGIN IF ( p = l ) THEN { Estamos al principio de la lista } anterior:=NIL ELSE BEGIN aux := l; encontrado := FALSE; WHILE ( aux^.siguiente <> NIL ) AND ( NOT encontrado ) DO IF ( aux^.siguiente = p ) THEN encontrado := TRUE; ELSE aux := aux ^.siguiente; IF encontrado THEN anterior := aux; ELSE anterior:=NIL; END; END; { De la funcin anterior }

Posicin Posicin Posicin Posicin

anterior siguiente del primer elemento del ltimo

Tema 10. Punteros

37

Tema 10. Punteros

38

Posicin siguiente a una dada


FUNCTION siguiente ( p : PunteroNodo; l : lista ) : PunteroNodo; { Devuelve la posicion siguiente a p en la lista l o NIL si no es posible } VAR q : PunteroNodo; encontrado : boolean; BEGIN { De la funcin siguiente } q := l; encontrado := FALSE; WHILE ( q <> NIL ) AND ( NOT encontrado ) IF ( q = p ) THEN encontrado := TRUE ELSE q := q^.siguiente; IF encontrado THEN siguiente := q^.siguiente ELSE siguiente:=NIL; END; { De la funcin siguiente }

Posicin del primer y ltimo elemento


FUNCTION primero ( l: lista ) : PunteroNodo; { Devuelve la posicin del primer elemento de la lista } BEGIN { De la funcin primero } primero := l; END; { De la funcin primero } { ---------------------------------------------------- } FUNCTION final ( l : lista ) : PunteroNodo; { Devuelve la ltima posicin de la lista l } VAR q : PunteroNodo; BEGIN { De la funcin final } q := l; IF (q<>NIL) THEN WHILE ( q^.siguiente <> NIL ) DO q := q^.siguiente; final := q; END; { De la funcin final }

Tema 10. Punteros

39

Tema 10. Punteros

40

Implementacin de listas con Nodo Cabecera


Consideraciones a tener en cuenta

Comprobar si la lista est vaca: l^.siguiente=NIL


L

Hasta ahora todos los nodos contenan informacin relevante Las operaciones de insercin y borrado deben considerar la posicin en la que se va a realizar la operacin Se puede utilizar otra implementacin en la que dichas operaciones fueran independientes de la posicin en las que se quiere realizar Para ello, se usar la Implementacin con Nodo Cabecera El primer nodo de la lista se llama cabecera y no contiene ningn elemento Siempre se deja el primer elemento vaco El primer nodo lgico (con informacin til) de la lista ser en realidad el segundo nodo fsico
L 5 8 1 8

Acceder al primer elemento de la lista: l^.siguiente^.elemento


L l^.siguiente^.elemento 5 8 7 8

Acceder a un elemento de la lista apuntado lgicamente por p: p^.siguiente^.elemento


p L 5 8 7 8

Comprobar si estamos en el ltimo elemento de la lista: p^.siguiente^.siguiente=NIL


p L

Lista enlazada de enteros con Nodo Cabecera


Tema 10. Punteros 41 Tema 10. Punteros

8
42

Implementacin de primitivas con Nodo Cabecera


PROCEDURE Crear ( VAR l: lista ); { Crea la lista vaca } BEGIN { Del procedimiento hacerNula } NEW ( l ); { Crea la celda cabecera } l^.siguiente := NIL; {Establece como ltimo elemento de la lista la cabecera } END; { Del procedimiento hacerNula } { ---------------------------------------------------- } FUNCTION vacia ( l: lista ) : BOOLEAN; { Devuelve True si la lista l est vaca, o FALSE en otro caso } BEGIN { De la funcin vaca } vacia := l^.siguiente = NIL; END; { De la funcin vaca }

Localizar la posicin de un elemento en la lista


FUNCTION localizar ( x : tipoElemento ; l : lista ) : PunteroNodo ; { Devuelve la posicin en que se encuentra el elemento x en la lista l } VAR p : PunteroNodo; encontrado : boolean; BEGIN { De la funcin localiza } p := l; encontrado := FALSE; WHILE ( p^.siguiente <> NIL ) AND ( NOT encontrado ) DO IF ( p^.siguiente^.elemento = x ) THEN encontrado := TRUE ELSE p := p^.siguiente; localizar := p; END; { De la funcin localiza }

Tema 10. Punteros

43

Tema 10. Punteros

44

Recuperar un elemento dada una posicin


PROCEDURE recuperar(VAR x: tipoElemento; p: PunteroNodo; l: lista ); { Recupera en x el elemento que ocupa la posicin p de la lista l } BEGIN { Del procedimiento recupera } IF (p^.siguiente<>NIL) THEN { No estamos al final de la lista } x:= p^.siguiente^.elemento ELSE error ( posicion errnea ); END; { Del procedimiento recupera }

Insertar un elemento
PROCEDURE insertar(x: tipoElemento ; p :PunteroNodo; VAR l : lista ); { Inserta el elemento x en la posicion p de la lista l } VAR q : PunteroNodo; BEGIN { Del procedimiento insertar } q := p^.siguiente; NEW ( p^.siguiente ); p^.siguiente^.elemento := x; p^.siguiente^.siguiente := q; END; { Del procedimiento insertar }

Tema 10. Punteros

45

Tema 10. Punteros

46

Borrar un elemento
PROCEDURE borrar ( p : PunteroNodo ; VAR l: lista ); { Borra el elemento que ocupa la posicin p de la lista l } VAR q : PunteroNodo; BEGIN { Del procedimiento borrar } IF (p^.siguiente<>NIL) THEN {posicin correcta de la lista} BEGIN q := p^.siguiente; p^.siguiente := q^.siguiente; DISPOSE ( q ); END; END; { Del procedimiento borrar }

Posicin anterior
FUNCTION anterior ( p: PunteroNodo; l : lista ) : PunteroNodo; { Devuelve la posicion anterior a la posicion p en la lista l } VAR aux: PunteroNodo; encontrado: boolean; BEGIN IF ( p = l ) THEN { Estamos al principio de la lista } error ( No hay posicion anterior ) ELSE BEGIN aux := l; encontrado := FALSE; WHILE ( aux^.siguiente <> NIL ) AND ( NOT encontrado ) DO IF ( aux^.siguiente = p ) THEN encontrado := TRUE; ELSE aux := aux ^.siguiente; IF encontrado THEN anterior := aux; ELSE anterior:=NIL; END; { De la funcin anterior }
47 Tema 10. Punteros 48

Tema 10. Punteros

Posicin siguiente
FUNCTION siguiente ( p : PunteroNodo ; l : lista ) : PunteroNodo; { Devuelve la posicion siguiente a p en la lista l } VAR q : PunteroNodo; encontrado : boolean; BEGIN { De la funcin siguiente } q := l; encontrado := FALSE; WHILE ( q <> NIL ) AND ( NOT encontrado ) IF ( q = p ) THEN encontrado := TRUE ELSE q := q^.siguiente; IF encontrado THEN siguiente := q^.siguiente ELSE error ( posicion incorrecta ); END; { De la funcin siguiente }

Tema 10. Punteros

49

Вам также может понравиться