Listas Enlazadas

June 22, 2018 | Author: Augusto Marin | Category: C++, Software Development, Software Engineering, Computer Programming, Computing
Share Embed Donate


Short Description

Descripción: Una breve exposición acerca de listas enlazadas con un sencillo programa ilustrativo....

Description

Listas Enlazadas Una Lista Enlazada (Linked List) es una colección lineal de estructuras autor-referenciadas llamadas nodos y conectadas por apuntadores. En una lista enlazada se puede tener acceso a los demás nodos vía apuntador, el cual va dentro de la estructura. Estas listas son dinámicas, se expanden en cuanto sea necesario otro nodo, y por convención el último nodo siempre apunta a un NULL. NULL. Las pilas y colas de espera son versiones de listas enlazadas, y los árboles, no propiamente lineales, también siguen el mismo principio. Las listas enlazadas, al igual que los arreglos, son una estructura de datos que pueden usarse para crear listas. Veamos ahora las ventajas que tienen las listas enlazadas. Estas son dinámicas, es decir, no tienen un número específico de elementos ya que pueden expandirse y contraerse según lo necesario. Son adecuadas cuando se prescinde el número de elementos que tendrá la lista. Los arreglos no, estos tienen un número definido de elementos tras la compilación y no se puede modificar. Los arreglos se llenan, pero las listas enlazadas sólo se llenan cuando no hay suficiente memoria para satisfacer la demanda de un nuevo nodo, esto en la actualidad ya no es problema. Nótese que los nodos de una lista enlazada no se disponen en memoria de manera contigua.

Ilustración 1

En el segmento de código del programa LinkList.cpp que se muestra en la Ilustración 1, sólo se presenta el contenido de la función main, main, el cual consta de un simple menú y un sencillo switch-case. switch-case. En la línea 79 se está

declarando un objeto de la clase ManagerList al cual llamaremos Admin. Admin. Observe el contenido de las líneas l íneas 82 a 112. 112. En el menú nos dan las opciones de crear un nuevo elemento ( nodo), borrarlo, reemplazar el contenido del elemento y mostrar la lista, y para ello se utilizan métodos del objeto Admin el cual no pertenece a una clase auto-referenciada, auto-referenciada, sino que ésta m aneja a una clase que si es auto-referenciada. Con ver ese segmento de código no se entenderá a grandes rasgos lo que es una lista enlazada, por lo que tendremos que adentrarnos a las partes del código que interesan. No iniciaré explicando el contenido de las clases o los métodos de clase línea por l ínea, sino que tenemos que comprender a detalle el comportamiento de la lista enlazada, así como el de las operaciones que se pueden hacer sobre ella. En este trabajo sólo se expondrá 3 de ellas; crear un nuevo nodo, borrar un nodo y reemplazar el contenido de un nodo. El cuarto, mostrar lista, es más para fines de visualización que manipulación en el programa.

Historia de una Lista Enlazada Empecemos haciendo una abstracción de cómo queremos ir armando una lista enlazada. Primero tenemos que imaginar que ésta se está armando. Para ello nos auxiliaremos de diagramas. En la Ilustración 2 tenemos el primer nodo de nuestra lista enlazada, éste contiene a la l etra a por lo que de esto deducimos que proviene de una estructura diseñada para almacenar datos de tipo char, char, pero esto no es lo que interesa por el momento. Al momento de crear la lista enlazada se creó un nodo por default que contiene a la letra a y además un apuntador enlazándolo con el siguiente elemento, que por el momento es NULL. NULL. Si se quiere agregar un nodo a la lista, necesitaremos imaginarnos como es que lo hará el programa. Necesitamos ayudantes, otros apuntadores que permitan facilitarnos la tarea. Los llamaremos first y last, last, y ambos apuntaran al primer elemento como se muestra en la Ilustración 3. Esto se hace pensando en que si queremos hacer una búsqueda, necesitamos saber dónde se encuentra el primer nodo de la lista, y si queremos agregar un nodo necesitamos saber en dónde se encuentra el último. Para eso sirven first y last, last, por lo que first siempre apuntará al primero y last siempre apuntará al último. first

a

a

NULL

Ilustración 2

NULL

last

Ilustración 3

Creemos un nuevo ayudante, actual, actual , éste será quien le ayude a last a crear un nuevo nodo, y que apuntará también al último nodo de la lista. Como se muestra en la Ilustración 4a, se ha creado un nuevo nodo que contiene la letra b y necesitamos enlazar a con b. Para esto le decimos a last que apunte a este nodo, ya que ahora será el último, y que el nodo a apunte ahora al nodo b referenciado por last. last. ¿Cómo hacemos para que el nodo a apunte ahora al nodo b referenciado por last? last? El apuntador del nodo a solo puede enlazarse con b mediante actual, actual, ya que en términos informáticos así es la sintaxis en un programa (Véase Ilustración 5), y eso se tratará en una sección posterior, ahora solo interesa entender a las listas enlazadas. Ya que se hizo que el nodo a apunte al nodo b mediante el apuntador actual, actual , b tendrá que apuntar a NULL por convención. El proceso terminado se muestra en la Ilustración 4b. ¿Por qué, sí  first hace referencia al mismo nodo que actual, actual, no utilizamos éste para ayudar a last? last? Porque está condición solo se cumple al momento de hacer un segundo nodo, sí queremos hacer un tercero, incluso el nodo 1000, no podemos mover a first de su lugar, ya que perderíamos el inicio de la lista, sin embargo actual puede ser movido a cualquier parte de la lista.

first a

NULL last

first

actual last

a

b

NULL

b

actual

Ilustración 4a

Ilustración 4b

Al principio esto puede ser un poco difícil de digerir para ser llevado a código, pero no hay que perdernos, más adelante será explicado con código y s e entenderá fácilmente.

Ilustración 5

Agreguemos un par de nodos más a la lista, el proceso es el mismo y los colocaremos por pasos: 1. 2. 3. 4. 5. 6.

Hacer que actual apunte a lo mismo que last. last. Crear un nuevo nodo y que last lo apunte. Darle nombre al nodo referenciado por last. last. Hacer que el nodo referenciado por actual apunte al nodo referenciado por last. last. Que el nodo referenciado por last apunte a un NULL. NULL. Y que actual regrese a apuntar al primer nodo de la lista.

El paso 6 será mejor comprendido en el transcurso de la explicación, ya que habíamos mencionado que actual iba a ser ayudante de last, last , pero él también tiene tareas distintas y necesitará un ayudante, al que desde ahora lo conoceremos como before. before. Si ejecutamos este algoritmo un par de veces más tendremos una lista como en la Ilustración 6. first

last

a

b

c

d

NULL

actual

Ilustración 6

Ahora, antes de mostrar como borrar nodos y reemplazar contenido de los nodos, necesitamos aprender a movernos por la lista, y es aquí en donde entran actual y before. before. Para empezar, veamos las acciones que necesitamos ejecutar para movernos a través de una lista enlazada: 1. actual y before apunten al mismo nodo. 2. actual apuntará al siguiente nodo, haciendo que acutal sea igual al enlace del nodo referenciado por before (que es el mismo que actual). actual ). 3. Los pasos 1 y 2 se ejecutaran mientras actual sea diferente de NULL y que el contenido del nodo referenciado por actual no sea el que queremos. Los pasos 1 y 2 se visualizan de la Ilustración 7 a la 10, simulando que queremos movernos al nodo c.

first

last

a

before

b

c

d

NULL

actual

Ilustración 7

Hasta la Ilustración 8 se han ejecutado los pasos 1 y 2 pero actual aún no está apuntando a un nodo que contenga c, y tampoco en NULL, NULL, así que se tiene que ejecutar nuevamente. first

last

a

before

b

c

d

NULL

actual

Ilustración 8

En la Ilustración 9 se ejecuta 1 del segundo ciclo y en la Ilustración 10 se ha ejecutado 2. first

last

a

b

before

c

d

NULL

actual

Ilustración 9

Vemos que hasta la Ilustración 10 se han terminado de ejecutar dos veces los pasos 1 y 2, y se observa que actual que no es NULL, NULL, ya está apuntando a un nodo que contiene c. Hasta aquí podemos dar por concluido el proceso de moverse por una lista enlazada. Sólo resaltaremos el hecho, de que al finalizar este método, before apunta a un nodo antes del nodo que apunta actual, actual , esto es de utilidad al momento de eliminar nodos, que es el método que se abordará a continuación. En el método de borrar, se reescribirán los enlaces, de manera que el nodo referenciado por before tenga ahora la dirección que tiene el nodo referenciado por actual. actual . De esta manera el nodo referenciado por actual queda libre para ser eliminado. first

last

a

Ilustración 10

b

c

before

actual

d

NULL

Entonces concluyendo, las acciones que deben ejecutarse para eliminar un nodo de una lista enlazada son las siguientes: 1. Mover el apuntador actual al nodo que se desea eliminar. 2. El nodo referenciado por before tiene el mismo enlace del nodo referenciado por actual. actual. 3. Eliminamos el nodo referenciado por actual. actual. 4. Si el nodo eliminado fue el último, last debe de hacer referencia al nodo que apunta before. before. 5. Luego actual debe hacer referencia al siguiente nodo, el apuntado por el nodo referenciado por before. before. 6. Si actual no es NULL se repetirán los pasos del 1 al 6 para eliminar los demás nodos que contengan el símbolo indeseado. Antes de ilustrar los pasos anteriores se aclara que el primer nodo de la lista no puede ser eliminado, ya que perderíamos el inicio de la lista y se verán afectados los demás nodos, puede ser reemplazado su contenido. No quiere decir que no se pueda eliminar bajo ninguna circunstancia, si puede ser eliminado, haciendo que first apunte al siguiente elemento de la lista, pero ese algoritmo no será detallado en esta sección, ya que el código que se mostrará más adelante simplemente no lo hace. Ilustremos ahora los pasos anteriores, suponiendo que el nodo que queremos eliminar es el nodo c, entonces en la Ilustración 10 ya se habrá ejecutado el paso 1. En la Ilustración 11 se ha ejecutado ya el paso 2, cuanto el nodo b, referenciado por before, hace referencia al nodo referenciado por el nodo c, referenciado por actual. first

last

a

b

c

before

actual

d

NULL

Ilustración 11

Tras ejecutar el paso 3 y 5, donde eliminamos el nodo referenciado por actual y este apunta ahora al nodo siguiente el diagrama queda como en la Ilustración 12. El paso 4 no se ha ejecutado ya que no fue el último nodo el que se eliminó. Esto se seguirá ejecutando hasta que actual apunte a NULL, NULL, por si todavía encuentra otro nodo c, pero como no es así, actual terminará apuntando a NULL y el proceso concluirá. Si se quiere utilizar este proceso nuevamente en el futuro, tenemos que reiniciar el valor de actual, actual , haciendo que apunte nuevamente al primer nodo de la lista, y entonces tendremos la Ilustración 13. No importa before donde apunte al finalizar. first

last

a

Ilustración 12

b

d

before

actual

NULL

first

last

a

b

actual

before

d

NULL

Ilustración 13

Por último tenemos el método que reemplaza elementos de los nodos por otros. Para ello tenemos que movernos, de la misma manera que lo hicimos anteriormente, a los nodos que contienen el dato que queremos cambiar, y reemplazarlo por otro, que será dado por un medio externo al programa, éste puede ser el usuario. Los pasos a seguir para ejecutar el método son: 1. 2. 3. 4.

Mover actual al nodo que se desea reemplazar. Escribir sobre él el nuevo símbolo. Y ejecutar los pasos 1 y 2 si actual no es NULL. NULL. Regresar a que actual apunte al primer nodo.

El paso 3 es para cuando hay más de un elemento del que se quiere reemplazar. Ya que terminamos de describir las operaciones que se usaron en el código, es momento de pasar esta abstracción a un código real.

Código de una Lista Enlazada En esta explicación asumiré que el lector ya conoce el lenguaje en el que está escrito el programa que es c++, así que sólo me limitaré a presentar los segmentos de código, y es tarea del lector analizar y comprender los algoritmos puesto que ya están hechas las analogías y las abstracciones. En la Ilustración 14 se presenta el famoso nodo, que es una clase auto-referenciada por un apuntador, la cual contiene dos métodos, que sirven para dar y obtener el valor del contenido.

Ilustración 14

Al principio del presente trabajo se hablo acerca de una clase que administraba la lista, y es la que se presenta en la Ilustración 15, en ella están los métodos abstraídos en la sección anterior, los cuales se presentan en las Ilustraciones posteriores.

Ilustración 15

Ilustración 16

En la Ilustración 16 se agregó el constructor que nos crea un nodo a inicialmente. ¿Recuerda la Ilustración 5?, yo no me he olvidado de que le iba a explicar el porqué de la sintaxis. Como first, first, actual, actual, before, before, last, last, son apuntadores a una clase, pueden tratárseles como objetos, pero no objetos cualesquiera. Como son objetos se puede acceder a sus miembros, por ejemplo link o setSym y getSym, getSym, pero de una manera especial. Con cualquier objeto haríamos objeto.link u objeto.setSym pero con ellos no, ya que, primero que nada, deben de contener la dirección de una clase u objeto, así que se le debe dar una asignación dinámica en memoria, empleando new, la palabra reservada de c++. Ejemplificando lo anterior, observe la línea 41 de la Ilustración 16. Para acceder a link u otro método, se usa el operador de referencia -> (guion mayor que) en vez de . (punto), como se muestra en la línea 36 de la Ilustración 16, dónde se le dice al constructor cuando crea el primer nodo, que éste debe hacer referencia a un NULL, NULL, y que se le tiene que ingresar el símbolo a mediante el método setSym. setSym. Esto es porque first, first, actual, actual, before y last son en sí apuntadores.

Ilustración 17

En la Ilustración 17, a partir de la línea 70 se presenta el método que imprime la lista en pantalla, éste lo hace hasta que actual sea NULL, NULL, y mientras eso no suceda camina por la lista imprimiendo cada símbolo, separando con -> para visualizar el flujo de expansión de la lista, al final, imprime NULL y vuelve a colocar actual al principio de la lista. Anexo a este documento usted puede encontrar el código completo del programa que simula una lista enlazada simple. En el programa encontrará varias líneas que no se explicaron en el análisis de la pasada sección, y se deja como tarea al lector que descubra el porqué de ellas, esto se logra con la práctica y el tiempo.

View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF