Descargar

Listas Enlazadas

Enviado por Naolly Dimeisons


Partes: 1, 2

  1. Resumen
  2. Introducción
  3. Fundamento teórico
  4. Bibliografía

Resumen

Las listas son estructuras lineales y dinámicas de datos. La principal ventaja del dinamismo lo representa el hecho de que se adquieren posiciones de memoria a medida que se necesitan y se liberan cuando ya no se requieren. Es decir, se llegan a expandir o contraer, dependiendo de la aplicación. El dinamismo de estas estructuras soluciona el problema de decidir cuánto espacio se necesita a priori, por ejemplo, en una estructura de datos estática como el arreglo. En este capítulo estudiaremos las listas lineales, circulares y doblemente ligadas. También se presentan estas estructuras con un enfoque orientado a objetos.

Introducción

En el presente trabajo se presenta la estructura de datos listas. Este es un tipo de estructura lineal y dinámica de datos. Lineal porque a cada elemento le puede seguir solo otro elemento; dinámica porque se puede manejar la memoria de manera flexible, sin necesidad de reservar espacio con antelación.

La principal ventaja de manejar un tipo dinámico de datos es que se puede adquirir posición de memoria a medida que se necesitan; éstas se liberan cuando ya no se requieren. Así es posible crear estructuras dinámicas que se expandan o contraigan, según se les agregue o elimine elementos. El dinamismo de estas estructuras soluciona el problema de decidir cuál es la cantidad óptima de memoria que se debe reservar para un problema específico. Sin embargo, es importante destacar que las estructuras dinámicas no pueden reemplazar a los arreglos en todas sus aplicaciones. Existen numerosos casos que podrían facilitarte ser solucionados aplicando arreglos, mientras que si se utilizan estructuras dinámicas, como las listas, la solución de estos problemas se complicaría.

Las listas ligadas son colecciones de elementos llamados nodos, el orden entre estos se establece por medio de un tipo de datos denominado punteros, apuntadores, direcciones o referencias a otros nodos. Por tanto, siempre es importante distinguir entre un dato de tipo apuntador y el dato contenido en la celda al cual este apunta. Se usará la notación P (^D para indicar que P es un apuntador al nodo D, Crear (P) para señalar el proceso de asignación de memoria al nodo P, y Quitar (P) para indicar el proceso inverso; es decir, cuando se libera una posición de memoria apuntada por P.

Las operaciones mas importantes que se realizan en las estructuras de datos son las de busqueda, insercion y eliminacion. Se utilizan tambien para comparar la eficiencia de las estructuras de datos y de esta forma observar cual es la estructura que mejor se adpta al tipo de problema que se quiere resolver. La busqueda por ejemplo, es una operación que no se puede realizar en forma eficiente en las listas. Por otra parte, las operaciones de insercion y eliminacion se efectuan de manera eficiente en este tipo de estructura de datos. Este capitulo se dedicara a las estructuras dinamicas lineales llamadas listas; entre se distinguen tres tipos: listas simplemente enlazadas ligadas, listas doblemente ligadas y listas circulares.

Fundamento teórico

  • Listas enlazadas

Una lista enlazada o estructura ligada, es una estructura lineal que almacena una colección de elementos generalmente llamados nodos, en donde cada nodo puede almacenar datos y ligas a otros nodos. De esta manera los nodos pueden localizarse en cualquier parte de la memoria, utilizando la referencia que lo relaciona con otro nodo dentro de la estructura.

Las listas enlazadas son estructuras dinámicas que se utilizan para almacenar datos que están cambiando constante mente. A diferencia de los vectores, las estructuras dinámicas se expanden y se contraen haciéndolas más flexibles a la hora de añadir o eliminar información.

 Las listas enlazadas permiten almacenar información en posiciones de memoria que no sean contiguas; y se almacena en los elementos nodos. Estos nodos poseen dos campos uno para almacenar la información o valor del elemento y otro para el enlace que determina la posición del siguiente elemento o nodo de la lista.

edu.red

Figura N° 1. Estructura de un nodo

Se compone de dos partes: una que contiene la información en sí y la segunda es un puntero y q su función es apuntar al siguiente nodo que haya.

  • Listas enlazadas simples

Una lista enlazada simple es una colección de nodos que tienen una sola dirección y que en conjunto forman una estructura de datos lineal. Cada nodo es un objeto compuesto que guarda una referencia a un elemento (dato) y una referencia a otro nodo (dirección).

La referencia que guarda un nodo a otro nodo se puede considerar un enlace o un puntero hacia el segundo nodo y el salto que los relaciona recibe el nombre de salto de enlace o salto de puntero. El primer nodo de una lista recibe el nombre de cabeza, cabecera o primero y el último es llamado final, cola o último (es el único nodo con la referencia a otro objeto como nula).

Un nodo de una lista enlazada simple puede determinar quien se encuentra después de él pero no puede determinar quien se encuentra antes, ya que solo cuenta con la dirección del nodo siguiente pero no del anterior.

edu.red

Figura

Figura N° 1.1 Se observa un puntero que va a apuntar al primer elemento que se ingresa y otro puntero que apuntara al último que será NULO.

Cuando tenemos una lista de la siguiente manera cada puntero apuntara al nodo siguiente y el puntero de la última lista como no tiene a donde apuntar entonces apuntara a NULO.

Para acceder a un nodo se utiliza la anterior con excepción del primero (no tiene a nadie antes) al que se tiene que acceder a través de un puntero externo a la lista, entonces se usa los punteros INICIO que es el que apunta constantemente al primero y el puntero ultimo q es el q apunta constantemente al último.

edu.red

Figura N° 1.2 Esquema de una lista simple enlazada.

Antes de analizar cada una de estas operaciones, se presentara un algoritmo que permite crear una lista simplemente ligada, al incorporar cada nudo al inicio.

Algoritmo 1.1 Crea_inicio

Crea_inicio

{Este algoritmo permite crear una lista simplemente ligada, agregando cada nuevo nodo al inicio de la misma}

{P y Q son variables de tipo puntero. Los campos del nodo son INFO, que sera el tipo de datos que se quiera almacenar en la lista, y LIGA de tipo apuntador, P apunta al inicio de la lista. RES es una variable de tipo entero}

  • 1. Crear (P) {Se crea un primer nodo de la lista simplemente ligada}

  • 2. Leer P^.INFO

  • 3. Hacer P^.LIGA(NILL

  • 4. Escribir "¿Desea ingresar mas nodos a la lista? SI:1 , NO : 0"

  • 5. Leer RES

  • 6. Mientras (RES=1) Repetir

Crear (Q)

Leer Q^.INFO

Hacer Q^.LIGA(P y P(Q

Escribir"¿ Desea ingresar mas nodos a la lista? SI:1 , NO : 0"

Leer RES

  • 7. Fin- mientras

  • 8. Fin

Veamos un ejemplo para ilustrar el fundamento de este algoritmo.

Ejemplo 1.1

Dados los siguientes datos: García, Perez, Lopez y Santos, genere una lista simplemente ligada mediante el algoritmo 1.1. En la siguiente figura se puede observar, paso a paso, cómo se va construyendo la lista.

Como observaramos en la figura 1.3, la lista quedo en orden inverso con respecto al orden en el que fueron dados, se debe agregar cada nodo al final de la lista. A continuacion se presenta un algoritmo que permite crear una lista simplemente ligada, al incorporar cada nuevo nodo al final.

edu.red

Figura 1.3 Creación de listas. A) Luego de crear el primer nodo. B) Luego de insertar a "Pérez". C) Luego de insertar a "López". D) Luego de insertar a "Santos".

NOTA: Las flechas discontinuas indican los cambios originados al insertar un nuevo elemento al inicio de la lista.

Algoritmo 1.2 Crea_final

Crea_final

{Este algoritmo permite crear una lista simplemente ligada, agregando cada nuevo nodo al final de la misma} {P, Q y T son variables de tipo apuntador. Los campos del nodo son INFO, que sera el tipo de datos que se quiera almacenar en la lista, y LIGA de tipo apuntador, P apunta al inicio de la lista. RES es una variable de tipo entero}

  • 1. Crear (P) {Se crea un primer nodo de la lista}

  • 2. Leer P^.INFO

  • 3. Hacer P^.LIGA(NILL T( P

  • 4. Escribir "¿Desea ingresar mas nodos a la lista? SI:1 , NO : 0"

  • 5. Leer RES

  • 6. Mientras (RES=1) Repetir

Crear (Q)

Leer Q^.INFO

Hacer Q^.LIGA( NILL, T^.LIGA(Q y T (Q{T apunta al ultimo nodo}

Escribir"¿ Desea ingresar mas nodos a la lista? SI:1 , NO : 0"

Leer RES

  • 7. Fin- mientras

  • 8. Fin

Veamos un ejemplo para ilustrar el funcionamiento de este algoritmo.

Ejemplo 1.2. Se utilizan los datos del ejercicio anterior para crear una lista aplicando el algoritmo 1.2. Es importante observar que en este algoritmo se utiliza otra variable de tipo apuntador para mantener la dirección del ultimo nodo de la lista, de tal manera que se pueda establecer el enlace entre este y el nuevo nodo. En la figura 1.3 se puede observar, paso a paso, como se va construyendo esta lista.

edu.red

Figura 1.3. Esquema de inserción al final.

  • Operaciones básicas de listas enlazadas simples

  • Recorrido de una lista simplemente enlazada

La operación de recorrido en una lista simplemente ligada consiste en visitar cada uno de los nodos que forman la lista. La isita puede implicar una operación simple; por ejemplo, imprimir la información del nodo, o una compleja, dependiendo del problema que se intenta resolver.

Para recorrer todos los nodos de una lista simplemente ligada se comienza con el primero. Se toma el valor del campo Liga de este y se avanza al segundo, y así sucesivamente hasta llegar al último nodo, cuyo campo LIGA tiene el valor NILL. En general, la dirección de un nodo, excepto el primero, está dada por el campo LIGA de su predecesor.

El algoritmo 2.1.1.presenta los pasos necesarios para recorrer una en forma iterativa.

Algoritmo 1.3 Recorre_iterativo

Recorre_iterativo (P)

{Este algritmo recorre una lista cuyo primer nodo esta apuntado por P}

{Q es una variable de tipo apuntador. INFO y LIGA son los campos de cada nodo de la lista}

  • Hacer Q( P

  • Miestras (Q NIL) Repetir

Escribir Q^.INFO

Hacer Q(Q^.LIGA {Apunta al siguiente nodo de la lista}

  • {Fin miestras}

  • FIN

Las listas se pueden manejar facilmente con procesos recursivos. El algoritmo constituye una versión recursiva para recorrer una lista simplemete ligada.

Algoritmo 1.4 Recorre_recursivo

Recorre_recursivo (P)

{Este algoritmo recorre una lista simplemente ligada en forma recursiva. P es un apuntador al nodo que se va a visitar. La primera vez trae la direccion del primer nodo de la lista}

{INFO y LIGA son los campos de cada nodo de la lista}

  • 1. Si P NIL entonces

Escribir P^. INFO

Llamar a Recorre_recursivo con P^.LIGA

{Llamada recursiva con el apuntador al siguiente nodo de la lista}

  • 2. Fin- Si

Veamos ahora la operación de insercion en listas simplemente ligadas.

  • Inserción en listas simplemente enlazadas

La operación de inserción en listas simplemente ligadas consiste en agregar un nuevo nodo a la lista, sin embargo, dependiendo de la posición en la que se deba insertar el nodo, se puede presentar diferentes casos, como los que se señalan a continuación.

  • Insertar un nodo al inicio de la lista.

  • Insertar un nodo al final de la lista.

  • Insertar un nodo antes que otro cuya información es X.

  • Insertar un nodo después de otra cuya información es X.

No se considerara en estos algoritmos el caso de que la lista este vacía; esta condición se puede incluir ya sea al inicio del algoritmo o en programa principal. Se considerara entonces que la lista en la cual se va a insertar el nodo ya existe -por lo menos tiene un nodo—.

  • a) Inserción al inicio de una lista simplemente ligada

En este caso el nodo se coloca al principio de la lista simplemente ligada, convirtiéndose en la primera de ellas. El proceso es relativamente simple como se puede observar en el siguiente algoritmo.

Algoritmo 1.5 Inserta_inicio

Inserta_inicio (PP, DATO)

{Este algoritmo inserta un nodo al inicio de una lista simplemente ligada. P es el apuntador al primer nodo de la misma, y DAO es la información que se almacenara en el nuevo nodo} {Q es una variable de tipo apuntador, INFO y LIGA son los campos de cada nodo de la lista}

1. Crear (Q)

2. Hacer Q^.INFO (DATO.Q^.LIGA(P y P ( Q

edu.red

Figura 1.4 inserción al inicio de una lista.

  • b)  Inserción al final de una lista simplemente Ligada

En este caso el nuevo nodo se coloca al final de la lista simplemente Ligada, convirtiéndose en el último, el algoritmo 5. 6 describe este proceso.

Algoriitmo 1.6 Inserta_Final

Inserta_final (P;DATO)

{este algoritmo insera un nodo final de una lista simplemente ligada. P es el apuntador al primer nodo de la lista, y DATOesla informacion que se almacenara en el nuevo nodo}

{Q y t son variables de tipo puntero. INFOy LIGA son los campos de cada nodo de la lista}

  • 1) Hacer T( P

  • 2) Mientras (T^.LIGANIL) repetir

{recorre la lista hastallegar al ultimo elemento}

Hacer T(T^.LIGA

  • 3) Fin-Mientras

  • 4) Crear {Q}

  • 5) Hacer Q^.INFO ( DATOQ^.LIGA ( NIL y T^.LIGA(Q

Ejemplo 1.4

En la figura 1.5 se presenta un ejemplo de insercion final de la lista. Si cada lista simplemente ligada se utilizaran dos apuntadores,uno al primer nodo y el otro al ultimo, entonces el proceso de insercion al final se simplificaria, ya que no seria necesario recorrerla toda para llegar al final. El nuevo nodo se podra incorporar directamente, como en el caso de insercion al inicio de la lista.

edu.red

Figura 1.5. Inserción al final de la lista

  • c) Insercion de un nodo antes que otro en la lista siplemnete ligada

Eneste tipo de insercion en las listas simplemente ligadas , el nuevo nodo se debe colocar antes de ptro nodo dado como referencia. Se pueden presentar diferentes caso; por ejemplo, que el nodo dado como refrencia no se encuentre en la lista o que el nuevo nodo a insertar se convierta en el primero . Se asume , como se ha señalado anteriormente, que la lista no esta vacia.

Algoritmo 1.7 Inserte_antes_X

Inserte_antes_X (P, DATO, X)

{Este algoritmo inserta un nodo dado como referencia en una lista simplemente ligada. P es el apuntador al primer nodo de la lista, DATO indica la información se almacenara en el nuevo nodo, y X representa el contenido – información—del nodo dado como referencia}

{Q, X y T son variables de tipo apuntador, INFO y LIGA son los campos de los nodos de la lista. BAND es una variable de tipo entero}

  • 1) Hacer Q( P y BAND ( 1

  • 2) Mientras ((Q^.INFO X) y (BAND =1) repetir

Si (Q^.LIGANIL) Entonces

Hacer T( Qy Q^.LIGA

Sino

Hacer BAND(0

Fin – Si

Fin – Mientras

  • 3) Si (BAND=1) Entonces

Crear(X)

Hacer X^.INFO ( DATO

Si (P=Q) Entonces {El nodo dado como refrencia es el primero}

Hacer X^.LIGA (P y P (X

Si no

Hacer T^.LIGA(X y X^.LIGA ( Q

Fin – Si

Si no

Escribir "el nodo dado como referencia no se encuentra en la lista "

Fin – Si

  • d) Insercion de un nodo despues de otro en una lista completamente ligada

En estetipo de insercion en listas simplemete ligadas, el nuevo nodo s debe colocar despues de otro lado coo referencia. Sepueden presentar diferentes casos: por ejemplo, que el nodo dado como referencia no se encuentre en la lista o queel nuevo se convierta en el ultimo de la lista. Se asume, como se haseñalado, que la lista no esta vacia. A continuacion se presenta el algoritmo correspondiente.

Algoritmo 1.8 Inserta_despues_X

Inserta_despues_X (P; DATO, X)

{Este algoritmo inserta un nodo despues de otro dado como referencia en una lista simplemente ligada P es el apuntador al primer nodo de la lista,DATO indica la informacion sea alamacenara el nuevo nodo, y X representa el contenido , informacion, del nodo dado como refrencia}

{Q yT son variables de tipo apuntador , INFO y LIGA son los campos de nodo de la lista BAND es una variable de tiipo entero}

  • Hacer Q(P y BAND (1

  • Mietras ((Q^.INNFOX)y(BAND=1)) Repetir

Si Q ^.LIGANIL Entonces

Hacer Q(Q^.LIGA

Si no

Hacer BAND( 0

  • Fin-Si

  • Fin – Mientras

  • Si (BAND=1) Entonces

Crear (T)

Hacer T^.INFO ( DATO, T^.LIGA ( Q^.LIGA (T

Si no

Escribir "El nodo dado como referencia no se encuentra en la lista"

  • Fin Si

edu.red

Figura.1.6. Las flechas discontinuas indican los cambios originados por la inserción de un nuevo nodo precediendo a otro, dado como referencia.

  • Eliminación en listas simplemente enlazadas

La operación de eliminacion en listas simplemnte ligadas consiste en eliminar un numero de la lista y liberar el espaciode memoria correspondiente. Dependiendo de la posicion en la que este se encuentre, se pueden presentar diferentes casos, como los que se señalan a continuacion:

  • Eliminar el primer nodo

  • Eliminar el ultimo nodo

  • Eliminar un nodo con informacion X

  • Eliminar el nodo anterior al nodo con informacion X

  • Eliminar el nodo posterior al nodo con informacion X

Cabe desacar que en los algoritmos que se presentan a continuacion no se consideran que la lista este vacia. Esta condicion se puede evaluar facilmente al inicio del algoritmo o bien e el programa principal.

  • a) Eliminar el primer nodo de una lista simplemente ligada

Esta operación es muy sencilla, ya que solo es necesario redefinir el apuntador al inicio de la lista. Si esta quedara vacia ( es decir, si la lista tenia solo un elemento), entonces apuntaria a NIL. Ene el siguiente algoritmo se describe este caso.

Algoritmo 1.9 Elimina_Inicio

Elimina_Inicio(P)

{Este algoritmo permite eliminar el primer elemento de una lista simplemente ligada. P es el apuntador al primer nodo de la lista}

  • Hacer Q ( P {Si la lista tuviera solo un elemento a P se le asigna NIL, que es el valor de Q^.LIGA. En caso contrario, queda con la direccion del siguiente nodo}

  • Hacer P( Q^.LIGA. {redefine el puntero al inicio de la lista}

  • Quitar (Q)

edu.red

Figura 1.7 muestra la eliminación del primer nodo utilizando el algoritmo anterior.

  • b) Eliminacion del ultimo nodo de la lista simplemente ligada

En este caso se debe eliminar el ultimo nodo de una lista simplemente ligada. Es importante observar que para alcanzar el ultimo nodo, se debe recorrer toda la lista, exepto si se usara un apuntador que indique su final. A continuacion se presenta un algoritmo de solucion, considerando que solamente se tiene un apuntador al inicio de la lista.

Algoritmo 1. 10 Elimina_ultimo

Elimina_ultimo (P)

{este algoritmo permite eliminar el ultimo nodo de una lista simplemente ligada. P es el apuntador al primer nodo de la lista}

{Q y T son variables de tipo apuntador. INFO y LIGA son los campos de los nodos de la lista}

  • Hacer Q(P

  • Si (P^.LIGA = NIL) {Se berifica si la lista tiene solo un nodo} entonces

Hacer P(NIL

sino

Mientras (Q^.LIGA!=NIL) Repetir

Hacer T(Q y Q(Q^.LIGA

Fin-Mientras

Hacer T^.LIGA(NIL

  • Fin-Si

  • Qyutar(Q)

edu.red

Figura 1.8. La flecha discontinua indica los cambios originados por la eliminación del último nodo de la lista.

  • c) Eliminar un nodo con informacion X de una lista simplemente ligada

La eliminacion de un nodo con informacion X es uno de los casos complicados una operación, porque se pueden presentar diferentes variantes. Por ejemplo, el nodo, puede ser el primero, el ultimo, el unico o no encontrarse en la lista. El algoritmo 1.11 demuestra este proceso.

Algoritmo 1.11 elimina_X

Elimina_X(P,X)

{este algoritmo elimina un nodo con informacion X de una lista simplemente ligada. P es el apuntador al primer nodo de la lista}

{Q y T son son variables de tipo apuntador. BAND es una variable de tipo entero, INFO y LIGA son los campos de los nodos de la lista}

  • Hacer Q(P y BAND( 1

  • Mientras ((Q^.INFO X) y (band = 1)) Repetir

Si Q^. LIGA NIL entonces

Hacer T(Q y Q ( Q^.LIGA

Sino

Hacer BAND ( 0

FIN SI

FIN – Mientras

  • Si (BAND=0) entonces

Enscribir "El elemento con informacion X no se encuentra en la lista"

Si (P= Q) {se verifia si el elemento a eliminar es el primero} entonces

Hacer P(Q^.LIGA

Sino

Hacer T^.LIGA ( Q^.LIGA

FIN-SI

  • FIN-si

edu.red

Figura 1.9. Eliminación de un nodo con información X.

  • d) Eliminar el nodo anterior al nodo con informacion X en una lista simplemente ligada

Este es el caso de eliminacion mas complicando en listas simplemente ligadas, porque tiene muchas variantes. Por ejemplo, el nodo con informacion X puede ser el primero – entonces no hay nada que eliminar -, el segundo – entonces hay que eliminar el primero de la lista-, estar en cualquier otra posicion, o bien no encontrarse en la lista.

Algoritmo 1.12 elimina_ante_X

elimina_ante_X (P,X)

{este algoritmo permite eliminar el nodo anterior al nodo que contiene la informacion X en una lista simplemente ligada. P es el apuntador al primer nodo de la lista}

{Q ,T y R son son variables de tipo apuntador. BAND es una variable de tipo entero, INFO y LIGA son los campos de los nodos de la lista}

edu.red

  • Búsqueda en listas simplemente enlazadas

La operación de búsqueda de un elemento en una lista simplemente ligada es muy fácil de realizar, aunque ineficiente ya que se lleva a cabo de forma secuencial. Se debe haber recorrido los nodos hasta encontrar el que estamos buscando o hasta que se llega al final de la lista. El algoritmo es similar a los que se desarrollaron para recorrer una lista en forma iterativa o recursiva.

Al igual que en las operaciones vistas anteriormente, existe diferencias en los algoritmos si las listas se encuentran ordenadas o desordenadas. Se comenzara en el primer término, con el algoritmo de búsqueda para listas simplemente ligadas que encuentran desordenadas.

edu.red

Figura 1.10. eliminacion de nodos . la flecha discontinua indica los cambios originados por la eliminacion del nodo anterior a un nodo dado como referencia

Algoritmo 1.13. Busqueda desordenada

Busqueda desordenada (P,X)

{Este algoritmo permite buscar el elemento con informacion X en una lista simplemente ligada que se encuentra desordenada. P es el apuntador al primer nodo de la lista}

{Q es una variable de tipo apuntador. INFO y LIGA son campos de los nodos de la lista}

Hacer Q ( P

Mientras ((QNIL) y (Q^.INFOX))

Hacer Q ( Q^.LIGA

FIN Mientras

SI (Q = NIL) entonces

Escribir " El elemento no se encuentra en la lista"

Sino

Escribir "el elemento si se encuentra en la lista"

Fin- si

Es importante destacar que con una simple modificacion en la condicion del ciclo del paso 2 se adapte este algoritmo para la busqueda de elementos en listas simplemente ligadas que se encuentran ordenadas. A continuacion se presenta el algoritmo de busqueda en listas simplemente ligadas que se encuentran ordenadas en forma ascendente.

Algoritmo 1.14. Busqueda_ordenada

Busqueda_ordenada (P,X)

{este algoritmo permite buscar el elemneto con informacion X en una lista simplemente ligada que se encuentra ordenada en forma ascendente. P es el apuntador al primer nodo de la lista}

{Q es una variable de tipo apuntador, INFO y LIGA son los campos de los nodos de la lista}

Hacer Q (P

Mintras ((QNIL) y (Q^.INFO/font>

Hacer Q ( Q^.LIGA

Fin- Mientras

Si ((Q=NIL) o (Q^.INFO > X)) entonces

Escribir "el elemento no se encuentra en la lista"

Sino

Escribir "el elemento si se encuentra en la lista"

Fin- Si

Todos los algoritmos pressentados tanto para la busqueda, insercion y eliminacion se pueden implementar de forma recursiva. A continuacion se muestra una version recursiva del algoritmo 1.13.

Algoritmo 1.15. Busqueda_recursivo

Busqueda_recursivo (P,X)

{este algoritmo permite buscar recursivamente a un elemento con informacion X en una lista simplemente ligada que se encuentra desordenada. P es el apuntador al primer elemento de la lista}

Si (P NIL) entonces

Si (P^.INFO = X) entonces

Escribir "el elemento se encuentra en la lista"

Sino

Llamar a Busqueda_recursivo con P^.LIGA y X

Fin-Si

Sino

Escribir "el elemento se encuentra en la lista"

Fin-Si

  • Listas circulares

Las listas circulares son similares a las listas simplemente ligadas. Sin embargo, tiene las características de que el último elemento de la lista apunta al primero, en lugar a apuntar al vacío NL.

Se define una lista simplemente ligada circular como una colección de elementos llamados nodos en el cual el último nodo apunta al primero. En la figura 5.14 se presenta una gráfica de una lista circular.

Las operaciones son similares a las operaciones en listas lineales; por tanto, no se trataran nuevamente en esta sección. Sin embargo es importante.

edu.red

Figura 2.1 Lista circular

edu.red

Figura 2.2 Lista circular con nodo cabecera

Señalar que para el caso de la operación de recorrido de listas circulares se necesita considerar algún criterio para detectar cuando se han visitado todos los nodos de la lista. Esto último con el propósito de evitar caer en ciclos infinitos. Una ´posible solución al problema planteado consiste en usar un nodo extra llamado nodo de cabecera, para indicar el inicio de la lista. Este nodo contendrá información especial, de tal manera que se distinga de los demás y así podrá hacer una referencia al principio de la lista. La figura 5.15 presenta una gráfica en una lista circular con nodo de cabecera.

En los algoritmos presentados para operar con listas simplemente ligadas se puede apreciar que solo se tiene acceso a un nodo y al sucesor de este. Si se necesitara su predecesor, por ejemplo, se tendrían que usar variables auxiliares (Véase el algoritmo 5.12). Una manera de evitar esta situación, es teniendo acceso a los nodos en cualquier orden, antecesor o sucesor, ya demás recorrer la lista del inicio al fin, o viceversa. Las listas que cuentan con esta facilidad son las doblemente ligadas. A continuación se presenta este tipo de estructuras.

  • Listas doblemente enlazadas

Una lista doblemente ligada es una colección de nodos, en la cual cada uno de ellos tiene dos apuntadores (fig. 3.1a), uno apuntando a su predecesor (LIGAIZQ) y otro a su sucesor (LIGADER). Por medio de estos punteros se podrá entonces avanzar o retroceder a través de la lista, según se tomen las direcciones de uno u otro puntador. La figura 3.1b) representa una lista doblemente ligada que almacena apellidos.

Para tener un fácil acceso a la información de la lista es recomendable usar dos apuntadores, P y F, que apunten al principio y al final de esta, respectivamente.

  • Operaciones básicas de listas doblemente enlazadas

Las operaciones que se pueden llevar a cabo en este tipo de estructuras son las mismas que con listas simplemente ligadas. En esta sección se presentarán las operaciones de:

  • Recorrido de lista.

  • Inserción de un elemento.

  • Borrado de un elemento.

edu.red

Figura 3.1 a) Estructura de un nodo. B) lista doblemente ligada.

  • Recorrido de una lista doblemente enlazada

Al tener cada nodo una doble liga, la lista se puede recorrer tanto del inicio al final, mediante las ligas derechas, como en sentido inverso; es decir, del final al principio, con las ligas izquierdas. Cualquiera que sea la direccion del recorrido, el algoritmo es similar al que se presenta para listas simplemente ligadas. Se deja al lector su diseño.

  • Inserción en listas doblemente enlazadas

La inserción de un elemento consiste en agregar un nuevo nodo a la lista y establecer los apuntadores correspondientes. No se considerará el caso de lista vacía. La inserción se puede llevar a cabo :

  • Al inicio de la lista doblemente ligada.

  • Al final de la lista doblemente ligada.

  • Antes/después de un nodo con información X.

  • a) Inserción al inicio de la lista doblemente ligada

En este caso el nuevo nodo se coloca al principio dse la lista y se establecen las listas correspondientes. El nuevo nodo insertado se convierte, entonces, en el primero de la lista doblemente ligada. El algoritmo 5.16 describe este proceso.

Algoritmo 5.16 Inserta_principio

Inserta_principio (P,DATO)

{ Este algoritmo inserta un nodo al inico de una lista doblemente ligada. P es el apuntador al primer nodo de la lista y DATO es la información que se almacenara ( en el nuevo nodo}

{Q es una variable de tipo apuntador. INFOR, LIGADER y LIGAIZQ son los campos de cada nodo de la lista}

  • Crear (Q)

Hacer Q^.INFOR (DATO, Q^.LIGADER(P. P^.LIGAIZQ ( Q.

Q^.LIGAIZQ(NIL y P(Q

  • b) Inserción al final de la lista doblemente ligada

En este caso el nuevo nodo se coloca al final de la lista doblemente ligada, convirtiéndose en el último. El algoritmo 5.17 describe este proceso.

Algoritmo 3.1. Inserta_final

Inserta_final (F, DATO)

(Este algoritmo inserva un nodo al final de una lista doblemente ligada. F es el apuntador al último nodo de la lista y DATO es la información que se almacenará en el nuevo nodo) (Q es una variable de tipo puntero. INFOR. LIGAIZQ y LIGADER son los campos de cada nodo de la lista)

Crear (Q)

Hacer Q^.INFOR ( DATO F^.LIGADER(Q, Q^.LIGAIZQ( F.

Q^.LIGADER ( NIL y F ( Q

edu.red

Figura 3.2. Inserción al final de la lista. Las flechas discontinuas indican los cambios originados en la lista doblemente ligada, por la inserción doblemente ligada.

Al trabajar con un apuntador al último elemento de la lista, F, la operación de inserción se simplifica notablemente ya que evita recorrer toda la lista.

  • c) Inserción de un nodo antes que otro en una lista doblemente ligada

En este caso el nuevo nodo se coloca precediendo a otro dado como referencia. Cabe señalar que solo se presentará la operación de inserción de un nodo antes de otro como referencia, ya que las operaciones Antes_que_otro_y Después_que_otro sion métricas.

Algoritmo 3.2. Inserta_antes_X

Inserta_antesX (P,DATO,X)

{Este algoritmo inserta un nodo antes de otro dado como referencia, con informacion X.P es el apuntador al primer nodo de la lista, y DATO es la información que se almacenara en el nuevo nodo}

{Q, T y R son variables de tipo apuntador, INFOR, LIGADER y LIGAIZQ son los campos de cada nodo de la lista}

1. Hacer Q( P

2. Mientras ((Q^.LIGADER NIL) y (Q^.INFOR X)) Repetir Hacer Q ( Q^.LIGADER

3. Fin- Mientras

4. Si ( Q^INFOR = X) entonces

Crear (T) (Se crea el nuevo nodo)

Hacer T^. INFOR ( DATO. T^-LIGADER ( Q.R ( Q^.LIGAIZQ

Y Q^-LIGAIZQ ( T

4.1. Si (P = Q) entonces

Hacer P ( T y T^.LIGAIZQ ( NIL

Si no

Hacer R^.LIGADER ( T y T^.LIGAIZQ ( R

4.2. Fin- Si

si no

Escribir ¨El elemento no se encuentra en la lista¨

5. Fin – Si

  • Eliminación en listas doblemente enlazadas

La operación de eliminación de un nodo en una lista doblemente ligada al igual que en el caso de las listas simplemente ligadas, consiste en eliminar un elemento de la lista, redefiniendo los apuntadores correspondientes y liberando el espacio de la memoria ocupado por el nodo. En la eliminación se pueden presentar diferentes casos, aunque algunos de ellos son simétricos, ya que cada nodo tiene apuntadores hacia delante – derecha – y atráz-izquierda

  • Eliminar el primer nodo.

  • Eliminar el último nodo.

  • Eliminar el nodo con información X.

  • Eliminar el nodo anterior/posterior al nodo con información X.

En los algoritmos que presentan la solución a los diferentes casos de borrado de un elemento de una lista, no se considera que ésta se encuentre vacía. Este caso, como ya se ha repetido en varias ocasiones, se puede controlar en el programa principal o bien con una condición simple al inicio de cada algoritmo.

  • a) Eliminar el primer nodo de una lista doblemente ligada

Consiste en quitar el primer nodo de la lista, cualquiera que sea su información reteniendo puntero al inicio de la misma. El algoritmo 5.19 describe este proceso.

Algoritmo 3.3 Elimina_inicio

Elimina_inicio (P,F)

{Este algoritmo elimina el primer elemento de una lista doblemente ligada. P y F son los apuntadores al primer y último nodo de la lista, respectivamente}

{Q es una variable de tipo apuntador: INFOR, LIGADER y LIGAIZQ son los campos de cada nodo de la lista}

1. Hacer Q ( P

2. Si (Q ^.LIGADER NIL.) (Verifica si la lista tiene solo un nodo) entonces

Hacer P ( Q^.LIGADER y P^.LIGAIZQ ( NIL

si no

Hacer P ( NIL y F ( NIL

3. (Fin del condicional paso 2)

4. Quitar (Q)

edu.red

Figura 3.3. Las flechas discontinuas indican los cambios originados en la lista doblemente ligada por la eliminación del primer nodo.

  • b) Eliminar el ultimo nodo de una lista doblemente ligada

Este caso es simétrico al anterior; consiste en eliminar el último nodo de una lista doblemente ligada y redefinir el apuntador al final de ella.

Algoritmo 3.4 Elimina_último

Elimina_último (P,F)

{Este algoritmo elimina el último elemento de una lista doblemente ligada P y F son los apuntadores al primero y último nodo de la lista, respectivamente}

1. Hacer Q ( F

2. Si (Q^.LIGAIZQ NIL) (Verifica si la lista tiene un solo nodo) entonces

Hacer F ( Q^.LIGAIZQ y F^.LIGADER ( NIL

si no

Hacer F ( NIL y P ( NIL

3.Quitar (Q)

figura 3.4 se presenta un ejemplo de eliminación del último nodo de una lista doblemente ligada el algoritmo anterior.

edu.red

  • c) Eliminar un nodo con información X

Estes caso consiste en eliminar el nodo que contenga la información X, y establece los apuntadores correspondientes entre su antecesor y su sucesor, respectivamente. Este caso tiene algunas variantes. El nodo que se quiere eliminar puede que no se encuentre en la lista, o bien que se halle y sea el primero , el último, el único, o que esté en cualquier posición intermedia de la estructura.

Algoritmo 3.5 Elimina_X

Elimina_X (P, F, X)

(Este algoritmo el nodo con información X de una lista doblemente ligada. P y F son los apuntadores al primero y último nodos de la lista, respectivamente)

(Q, T y R son variables de tipo apuntador. INFOR, LIGADER y LIGAIZQ son los campos de cada nodo de la lista)

edu.red

  • d) Eliminar el nodo anterior al nodo con información X

En este caso se trata de eliminar el nodo anterior a uno dado como referencia que tenga la información X. El caso también tiene algunas variantes. Puede ser que el nodo con información X no se encuentre en la lista o bien se encuentre, y sea el primero en ese caso no hay nada que eliminar—, el segundo— se elimina el primero de la lista—, o se encuentre en cualquier otra posición. El algoritmo 5.22 describe los pasos necesarios para llevar a cabo esta operación.

Algoritmo 3.6 Elimina_antes_X

Elimina_antes_X (P,X)

{Este algoritmo elimina, si se puede, el nodo anterior a aquel que contiene la información X.P es el apuntador al primer nodo de la lista}

{Q, T y R son variables de tipo apuntador, INFOR, LIGADER y LIGAIZQ son los campos de cada nodo de la lista}

edu.red

edu.red

La figura 3.5. contiene un ejemplo de eliminación, mediante el algoritmo anterior.

edu.red

Figura 3.6 eliminación de nodos. Las flechas discontinuas indican los cambios originados e la lista doblemente ligada por la eliminación de un nodo.

  • Listas circulares doblemente enlazadas

En las listas doblemente ligadas circulares, el campo liga izquierda del primer nodo de la lista apunta al último, y el campo liga derecho de éste apunta al primero. La figura 3.6 representa una estructura de este tipo.

La principal ventaja de las listas circulares es que permiten la navegacion en cualquier sentido a travéz de la misma y, además,se puede recorrer toda la lista partiendo de cualquier nodo, siempre que tengamos un apuntador a éste. Sin embargo, debemos destacar que es necesario establecer condiciones adecuadas para detener el recorrido de una lista y evitar caer en ciclos infinitos. Al igual que en el caso de listas simplemente ligadas circulares, se suele utilizar un nodo de cabecera ( fig. 3.6) .

Este nodo tendrá las características descritas anteriormente y servirá como referencia para detectar cuándo se ha recorrido totalmente la lista.

Partes: 1, 2
Página siguiente