Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Punteros
Introducción
Memoria de un ordenador
Gestión del Heap
Tipo de dato puntero
Tema 10.
Definición
Inicialización y liberación de memoria
Manejo Dinámico de
Operaciones básicas
El operador @
Memoria. Punteros
Procesamiento de listas
Listas con arrays
Listas con punteros
TDA Lista con punteros
TDA Lista con Nodo Cabecera
1
Inicialización y liberación de
El tipo de dato puntero
memoria
Un puntero es un objeto cuyo contenido es la dirección
de memoria que ocupa otro objeto de nuestro programa Son dos operaciones importantes
Para indicar al compilador que debe reservar espacio en el heap hay
El rango de valores válidos será el de las direcciones de
memoria capaces de ser accedidas por el procesador del que inicializar el puntero con NEW(id_puntero)
ordenador, más una dirección de memoria especial, que Al realizar la inicialización, se asigna un bloque del heap en tiempo de
se corresponde con el puntero nulo ejecución y se marca como ocupado
El puntero nulo recibe nombres diferentes dependiendo El bloque permanece ocupado hasta que el programa libera
del lenguaje (Pascal – NIL, C – NULL) explícitamente esa zona de memoria mediante la operación
Declaración de una variable tipo puntero DISPOSE(Id_puntero)
Ejemplos
Ejemplos
VAR q ? p ? Errores comunes TYPE
q,p:^integer; Var Empleado= RECORD
BEGIN p:^integer; Codigo:Integer;
q ? p ? Begin Nombre:string[30];
New(p); p^
NEW(p) Edad:Integer;
p^
q ? p 30 p:=2300; {asignar a p la sueldo:real;
p^:=30; p^ dirección 2300} END; 1001
NEW(p); {se reserva un VAR
q ? p 350 p Ana García
p^:=p^*10+50; p^ nuevo bloque para p:^Empleado;
p sin haber liberado BEGIN 35
? p 350 el bloque antiguo} ……
New(q); q
q^ p^ DISPOSE(p); NEW(p); 1754
p^:=2300; {intenta acceder al p^.codigo:=1001;
q^:=p^; q 350 p 350 contenido del bloque P^.nombre:=‘Ana García’;
q^ p^ que ya ha sido P^.edad:=35;
liberado} P^.sueldo:=1754;
p^:=p^+q^; q 350 p
p^
700 p:=NIL ……
q^
IF (p^=0) THEN… {intenta acceder DISPOSE(p);
al contenido de un
q:=p; q 350 p 700 ……
p^ q^ puntero nulo} END;
End;
Tema 10. Punteros 11 Tema 10. Punteros 12
2
Algunas consideraciones Ejemplo paso parámetros
El puntero nulo PROGRAM
{-- programa principal ------}
Se dice que tiene el valor NIL (o NULL) Ejemplo_paso_parametros;
BEGIN
Antes de utilizar un puntero, debemos asegurarnos de que su TYPE Tptr=^integer;
valor no es NIL referencia(p);
VAR p:Tptr;
El gestor de memoria devuelve NIL cuando no ha sido posible writeln(p^);
{--- ejemplo de paso por referencia--}
la asignación de memoria requerida por la llamada NEW Dispose(p);
PROCEDURE referencia(VAR q:Tptr);
Paso de parámetros BEGIN
valor(p);
A la hora de pasar como parámetro un puntero, debe realizarse writeln(p^);
por referencia, siempre y cuando lo que se haga dentro del New(q);
END.
módulo llamado afecte no al objeto apuntado por el puntero, q^:=20;
sino al propio puntero END;
En cambio, si lo que realizamos en el interior del módulo {--- ejemplo de paso por valor ---}
llamado afecta no ya al puntero sino al objeto apuntado por el
mismo, entonces es indiferente el modo de pasar el parámetro PROCEDURE valor(q:Tptr);
ya que ambos punteros - el puntero existente en memoria BEGIN
principal y el creado en la pila - apuntan al mismo espacio de New(q);
memoria
q^:=20;
END;
Tema 10. Punteros 13 Tema 10. Punteros 14
Insertar un elemento
Listas con arrays PROCEDIMIENTO insetar(
VAR lista:LISTAENTEROS; {lista de enteros}
Se utiliza un array unidimensional para almacenar la VAR NumElem:ENTERO; {Nº de elementos de la lista}
lista, de manera que el i-ésimo elemento de la lista se elem:ENTERO; {elemento a insertar}
corresponde con el i-ésimo elemento del array pos:ENTERO ) {posición en la que se inserta}
TIPO VARIABLES
listaenteros=ARRAY[1..Limite] de ENTEROS i:ENTERO
VARIABLES INICIO
lista:listaenteros PARA i=0 HASTA NumElem-pos HACER
lista[NumElem+1-i] ← lista[NumElem-i]
Operaciones inmediatas {Desplazar todos los elementos a partir de}
Leer y escribir los elementos de la lista FIN_PARA {la posición en la que se va a insertar}
Buscar un elemento de la lista Lista[pos] ← elem {Insertar el elemento en la posición ‘pos’}
NumElem ← NumElem+1 {Incrementar el nº total de elementos}
Limitaciones FIN_PROC
Los arrays deben tener una longitud fija (son estructuras Lista es (34,52,12,6,10) y NumElem es 6
estáticas) Llamada al procedimiento INSERTAR(lista,NumElem,38,3)
Operación de inserción y eliminación (algoritmos sencillos pero 34,52,12 ,6 ,10
ineficientes)
34,52,38,12,6,10
Tema 10. Punteros 17 Tema 10. Punteros 18
3
Listas enlazadas Lista enlazada
Cuándo usar estructuras dinámicas
BOA
El tamaño de una lista no se puede predecir a priori GATO
PERRO
Las operaciones de inserción y borrado son frecuentes
Las listas enlazadas son una secuencia de nodos que se enlazan LEON
mediante un enlace o puntero Dirección
155
Lista
156
5 8 1 9 ………… 8
157 GATO 150
158
Lista enlazada de enteros con punteros
………………
Crear una lista a partir de datos de entrada Crear una lista a partir de los
PROCEDURE crea_lista5_teclado(VAR l:lista);
VAR
datos de un fichero
i:INTEGER; x:TipoElemento; p:PunteroNodo; PROCEDURE crea_lista_fichero(VAR l:lista;VAR F:FIC);
BEGIN {Se supone que el fichero ya está creado y asignado. El tipo FIC se definió en el programa principal}
VAR
WRITELN('Introduzca 5 datos de entrada para crear la lista'); i:INTEGER; x:TipoElemento; p:PunteroNodo;
NEW(l); BEGIN
READLN(x); RESET(F);
IF NOT EOF(F) THEN BEGIN
l^.elemento:=x; READ(F,x); NEW(l);
p:=l; l^.elemento:=x;
i:=2; p:=l;
WHILE (i<=5) DO WHILE NOT EOF(F) DO
BEGIN
BEGIN READ(F,x);
READLN(x); NEW(p^.siguiente);
NEW(p^.siguiente); p:=p^.siguiente;
p^.elemento:=x;
p:=p^.siguiente; END;
p^.elemento:=x; p^.siguiente:=NIL;
i:=i+1; END
ELSE WRITELN(‘El fichero está vacío. No se puede crear la lista);
END;
CLOSE(F);
p^.siguiente:=NIL; END;
END;
4
Añadir un elemento al final de la
Imprimir una lista
lista
PROCEDURE imprime_lista(l:lista);
PROCEDURE add_elemento(VAR l:lista;x:TipoElemento);
VAR VAR
p:PunteroNodo;
p:PunteroNodo; BEGIN
BEGIN IF (l=NIL) THEN BEGIN
NEW(l);
p:=l; l^.elemento:=x;
l^.siguiente:=NIL;
WHILE (p<>NIL) DO END
ELSE BEGIN
BEGIN p:=l;
WHILE (p^.siguiente<>NIL) DO
WRITELN(p^.elemento); p:=p^.siguiente;
p:=p^.siguiente; NEW(p^.siguiente);
p:=p^.siguiente;
END; p^.elemento:=x;
p^.siguiente:=NIL;
END; END;
END;
5
Primitivas con el TDA Lista con Implementación de primitivas
Punteros (Crear lista y Comprobar si vacía)
Operaciones de la lista enlazada PROCEDURE crear ( VAR l: lista );
Crear lista vacía { Crea la lista vacía }
BEGIN { Del procedimiento hacerNula }
Comprobar si la lista está vacía
l:= NIL; {Establece como último elemento de la lista la cabecera }
Localizar la posición END; { Del procedimiento hacerNula }
Recuperar elemento de una posición
Insertar elemento { ---------------------------------------------------- }
Borrar elemento FUNCTION vacia ( l: lista ) : BOOLEAN;
{ Devuelve True si la lista l está vacía, o FALSE en otro caso }
BEGIN { De la función vacía }
vacia := l = NIL;
END; { De la función vacía }
6
Posición anterior a una dada
Primitivas adicionales FUNCTION anterior ( p: PunteroNodo; l : lista ) : PunteroNodo;
{ Devuelve la posicion anterior a la posicion p en la lista l. Si p no es una posición válida
o estamos al principio de la lista devuelve NIL }
VAR
aux: PunteroNodo;
Posición anterior encontrado: boolean;
BEGIN
Posición siguiente IF ( p = l ) THEN { Estamos al principio de la lista }
anterior:=NIL
Posición del primer elemento ELSE BEGIN
aux := l;
Posición del último 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 función anterior }
7
Implementación de primitivas con Localizar la posición de un
Nodo Cabecera elemento en la lista
FUNCTION localizar ( x : tipoElemento ; l : lista ) : PunteroNodo ;
PROCEDURE Crear ( VAR l: lista );
{ Devuelve la posición en que se encuentra el elemento x en la lista l }
{ Crea la lista vacía } VAR
BEGIN { Del procedimiento hacerNula } p : PunteroNodo;
NEW ( l ); { Crea la celda cabecera } encontrado : boolean;
l^.siguiente := NIL; {Establece como último elemento de la lista la cabecera } BEGIN { De la función localiza }
END; { Del procedimiento hacerNula } p := l;
{ ---------------------------------------------------- } encontrado := FALSE;
FUNCTION vacia ( l: lista ) : BOOLEAN; WHILE ( p^.siguiente <> NIL ) AND ( NOT encontrado ) DO
{ Devuelve True si la lista l está vacía, o FALSE en otro caso } IF ( p^.siguiente^.elemento = x ) THEN
BEGIN { De la función vacía } encontrado := TRUE
vacia := l^.siguiente = NIL;
ELSE p := p^.siguiente;
localizar := p;
END; { De la función vacía }
END; { De la función localiza }
8
Posición 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 función 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 función siguiente }