UN EJEMPLO DEL USO DE PUNTEROS: LAS LISTAS ENLAZADAS

Anuncio
UN EJEMPLO DEL USO DE PUNTEROS: LAS LISTAS ENLAZADAS
Estructuras de datos estáticas y dinámicas
En capítulos anteriores se han estudiado estructuras de datos estáticas (conjuntos, arrays,
registros...), cuya característica esencial es que su almacenamiento en memoria (número de
elementos) se determina a priori en el momento de escribir el programa y se fija durante la
compilación. Durante la ejecución del programa sus valores se pueden modificar, pero no se puede
cambiar el número de elementos de la estructura, que es fijo.
Para paliar este inconveniente, se utilizan las estructuras dinámicas de datos, que son aquellas en las
que podemos aumentar o reducir su número de elementos (nodos) de acuerdo con las necesidades
del programa. Las estructuras dinámicas de datos se dividen en dos grandes grupos: lineales (listas,
pilas, colas...) y no lineales (árboles, grafos...).
Definición de lista enlazada
Son estructuras dinámicas lineales de elementos llamados nodos, que se encuentran enlazados o
relacionados cada uno con el siguiente mediante un enlace o puntero. Cada nodo debe tener dos
campos: un campo (info) que contiene el valor de ese elemento y un campo (enlace o puntero) que
indica la posición del siguiente elemento.
Existe una marca para fin de lista, que es la constante NIL, representada por una barra inclinada en
el último nodo.
Declaración de un nodo
Seguidamente indicamos cómo se declara un puntero para referenciar un nodo correspondiente a
una estructura dinámica de datos:
Type
Tptro = ^Tnodo;
Tnodo = Record
Info: TipoDato; (* cualquier tipo
de datos definido
por el usuario *)
Enlace: Tptro
End;
Observe que la definición de Tptro precede a la definición del registro tipo Tnodo. Esta es una de
las pocas situaciones en las que está permitido utilizar un identificador (Tnodo) antes de ser
definido.
Para las operaciones que a continuación se describen (inicialización, insertar al principio, insertar al
final, recorrido y eliminación de un nodo de una lista), se declara una lista de la siguiente forma:
Type
Tinfo: string[9];
Tlista = ^Tnodo;
Tnodo = Record
info: Tinfo;
enlace: Tlista
End;
Var
L: Tlista;
Inicialización de una lista enlazada
Construye una lista vacía, es decir, que no contiene elementos:
Procedure Inicializar(var L: Tlista);
Begin
L:=nil (* fija el puntero del primer nodo a nil *)
End;
Insertar al principio de la lista
Crea un nodo y lo pone en el primer lugar de la lista:
Procedure InsertarAntes (var L: Tlista; x: Tinfo);
Var
Aux: Tlista;
Begin
New(Aux);
Aux^.info:=x; (*almacena la información en el nuevo nodo*)
Aux^.enlace:= L; (*1:insertar el nodo al principio de la lista*)
L:=aux; (*2:la cabecera de la lista apunta al nuevo nodo*)
End;
Insertar al final de la lista
Crea un nodo y lo pone en el último lugar de la lista:
Procedure InsertarDespués(var L: Tlista, x: Tinfo);
Var
Anterior, Actual, Aux: Tlista;
Begin
New(Aux);
Aux^.info:=x; (*almacena la información en el nuevo nodo*)
Aux^.enlace:=nil; (*el nuevo nodo apunta a NIL*);
Anterior:= nil;
Actual:=L;
(* Buscar el último nodo *)
While Actual <> nil do
Begin
Anterior:=Actual;
Actual:=Actual^.enlace;
End;
(* Si la lista está vacía, entonces el primer puntero apunta al nuevo nodo *)
If Anterior = nil then
L:=aux
Else
Anterior^.enlace:=Aux;
End;
Recorrido de una lista
La operación de imprimir los datos de una lista se conoce como recorrido. Se debe comenzar por la
cabecera de la lista y seguir con todos los punteros de la lista, imprimiendo todos los campos info
(datos):
Procedure ImprimirLista(L: Tlista),
Begin
While L<>nil do
Begin
Writeln(L^.info); (* imprime el valor del nodo *)
L:=L^.enlace
End
End;
Eliminar un nodo
Borrar o eliminar el nodo al que se está apuntando, exige conectar el nodo precedente al nodo
después del que se desea borrar:
Procedure Borrar(var L: Tlista, N: Tlista);
(* N es el nodo a borrar *)
var
q1: Tlista (* Puntero que se mueve por la lista *)
begin
if N=L then (* Si es el primer elemento *)
L:=L^.enlace (* Eliminar N^ *)
else
begin
(* sino, encontrar elemento antes de N^*)
q1:= L;
while q1^.enlace<>N do
q1:=q1^.enlace;
q1^.enlace:=N^.enlace (* 1:eliminar N^ *)
end;
dispose(N); (* 2: liberar memoria *)
end;
Descargar