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

Estructura de Datos y Listas Encadenadas

(Septiembre-2011)

Contenido
INTRODUCCIN ....................................................................................................................................... - 1 MANEJO DINMICO DE MEMORIA .......................................................................................................... - 1 CDIGO FUENTE DE NODE.CS ....................................................................................................................... - 2 IMPLEMENTACIN DE LISTA ENCADENADA BSICA................................................................................. - 4 AGREGACIN ........................................................................................................................................... - 4 EXTRACCIN ............................................................................................................................................ - 6 COMPORTAMIENTO DE LISTAS ENCADENADAS BSICA ......................................................................................... - 8 Constructores ................................................................................................................................... - 8 Propiedades ..................................................................................................................................... - 8 Mtodos .......................................................................................................................................... - 8 CDIGO FUENTE DE LIST.CS ......................................................................................................................... - 9 CDIGO FUENTE PARA PROBAR LISTAS ENCADENADAS BSICAS............................................................................ - 11 Person.cs........................................................................................................................................ - 12 Program.cs..................................................................................................................................... - 13 CUESTIONES DE PERFORMANCE ............................................................................................................ - 14 CDIGO FUENTE DE LIST.CS MEJORADO ........................................................................................................ - 15 CONSIDERACIONES ................................................................................................................................ - 18 -

Estructura de Datos y Listas Encadenadas

Introduccin
Voy a continuar con las listas como tipo de dato abstracto y sus implementaciones o estructuras de datos. En esta oportunidad le toca a las listas encadenadas. Este tipo de dato abstracto representa a aquellas listas que en tiempo de ejecucin pueden aumentar o disminuir su tamao sin afectar la performance. Ya vimos que los lenguajes orientados a objetos pueden redimensionar los arreglos, pero eso conlleva un proceso adicional que puede causar problemas en una aplicacin. Las listas encadenadas son la base para la conformacin de listas ms complejas, tanto a nivel de memoria primaria como secundaria, en algunos aspectos aventajan a las listas de almacenamiento en secuencia como por ejemplo su flexibilidad; sin embargo su implementacin en entornos no orientados a objetos suele ser difcil y su ejecucin bastante ms lenta.

Manejo dinmico de memoria


El manejo dinmico de memoria es una caracterstica que proveen los lenguajes de programacin de manera que en tiempo de ejecucin el usuario puede disponer de ms memoria o devolver la que no est utilizando. En las listas encadenadas, debido a que el sucesor inmediato de un elemento no necesariamente se encuentra fsicamente a continuacin de ste, se les puede suministrar la memoria de forma dinmica, es decir a medida que se va necesitando. Consecuentemente cada elemento necesita de un "enlace" para almacenar la direccin donde se encuentra el siguiente elemento. En los lenguajes no orientados a objetos, este "enlace" se implementa como un puntero y en los lenguajes orientados a objetos este "enlace" recibe el nombre de "referencia". En ambos casos existe el concepto de una estructura de datos conocida como "nodo" que resulta ser un registro (en los lenguajes no orientados a objetos) o un objeto (en los lenguajes orientados a objetos) que consta esencialmente de dos partes, una de ellas informacin o datos y la otra enlaces (al menos uno).

Cada vez que hace falta implementar una lista de lo que sea que el cliente quiera se debe declarar la estructura interna del nodo dado que ah es donde estn los datos. Esto nos puede llegar a volver locos, adems es inmanejable la cantidad de declaraciones de nodo que podramos llegar a tener en una aplicacin. Consecuentemente hace falta realizar una implementacin con programacin genrica que nos permita introducir dentro del nodo lo que sea necesario. En muchas implementaciones suele utilizarse una referencia del tipo "object" que es la base de todos los objetos que el lenguaje puede manejar, incluso a esto le llaman programacin genrica cuando en realidad no lo es. Si el lenguaje permite programacin genrica esto es utilizando un "patron" que en tiempo de

-1-

Estructura de Datos y Listas Encadenadas ejecucin se cambia por el tipo que el desarrollador indica entonces es mejor utilizar esta tcnica porque de ese modo se est realizando un fuerte control de tipos, que cuando se utiliza "object" no puede hacerse. Bajo esta premisa y como el nodo no presenta comportamiento particular solamente tendr en la estructura interna una referencia del tipo que se indique al momento de construir los objetos (programacin genrica) y un enlace (referencia) al siguiente nodo. Se pueden implementar varios constructores adems del constructor por defecto para poder crear nodos de distintas maneras. Se facilita el acceso a la estructura interna mediante getters y setters para cada miembro de la misma. Nota: En C# se incorpora la posibilidad de declarar "Properties" (propiedades) que es una porcin de cdigo (parecida a un mtodo) que la mayora de las veces permite el acceso a campos de la estructura interna. Lo hace mediante dos bloques de cdigo get { ... } y set { ... }, obviamente el get es para leer el valor del campo y el set es para fijar o poner un valor en el campo. Internamente el compilador de C# genera un mtodo por cada uno de estos bloques; en el caso del nodo para la propiedad Item se genera getItem() y setItem(ELEMENTO value) que es igual a lo que un programador de Java hace cuando genera los getters y setters, la diferencia es que en Java cuando se tiene un objeto Node miNodo, se debe hacer lo siguiente miNodo.setItem(algun_valor), en cambio en C# se puede hacer miNodo.Item = algun_valor. Indudablemente esta ltima forma es ms natural, pero debemos recordar que eso se logra gracias al compilador que "traduce" las sentencias al formato de mtodo.

Cdigo fuente de Node.cs


namespace DemoLista1 { /// <summary> /// Clase para representar un nodo de listas enlazdas /// </summary> /// <typeparam name="ELEMENT">Tipo de dato del elemento</typeparam> internal class Node<ELEMENT> { #region Estructura Interna /// <summary> /// Mantiene el elemento en el nodo /// </summary> private ELEMENT item; /// <summary> /// Mantiene el enlace al siguiente nodo /// </summary> private Node<ELEMENT> next;

-2-

Estructura de Datos y Listas Encadenadas


#endregion #region Constructores /// <summary> /// Constructor por defecto, inicializa los campos de la estructura /// interna en valores por defecto /// </summary> public Node() { this.item = default(ELEMENT); this.next = null; } /// <summary> /// Constructor especializado, permite fijar el elemento del nodo /// </summary> /// <param name="item">Elemento en el nodo</param> public Node(ELEMENT item) : this() { this.item = item; } /// <summary> /// Constructor especializado, permite fijar el elemento del nodo /// y el valor del enlace al siguiente nodo /// </summary> /// <param name="item">Elemento en el nodo</param> /// <param name="next">Enlace al siguiente nodo</param> public Node(ELEMENT item, Node<ELEMENT> next) : this() { this.item = item; this.next = next; } /// <summary> /// Constructor especializado, permite fijar el enlace al /// siguiente nodo /// </summary> /// <param name="next">Enlace al siguiente nodo</param> public Node(Node<ELEMENT> next) : this() { this.next = next; } #endregion #region Propiedades Getters and Setters /// <summary> /// Facililta el acceso al elemento en el nodo /// </summary> public ELEMENT Item { get { return this.item; } set {

-3-

Estructura de Datos y Listas Encadenadas


this.item = value; } } /// <summary> /// Facilita el acceso al enlace al siguiente nodo /// </summary> public Node<ELEMENT> Next { get { return this.next; } set { this.next = value; } #endregion } } }

Implementacin de lista encadenada bsica


Una lista se utiliza para almacenar informacin de mismo tipo, con la caracterstica de que puede contener un nmero indeterminado de elementos (mientras haya memoria) y que estos elementos mantienen un orden explcito (al menos el de la forma en que se introducen en la lista). Este ordenamiento explicito implica que cada elemento mantiene un enlace al siguiente elemento. Una lista es una estructura de datos dinmica, el nmero de elementos en la lista puede variar rpidamente en un proceso, aumentando por agregaciones o disminuyendo por extracciones. Las agregaciones se pueden realizar por cualquier punto de la lista; por la cabeza (inicio), por el final (cola), a partir o antes de un elemento determinado de la lista. Las extracciones tambin se pueden realizar en cualquier punto; adems se extraen elementos dependiendo del valor de un atributo del elemento mismo.

Agregacin
Una de las formas en que se puede agregar un elemento por la cabeza (head) de la lista. Obviamente si la lista est vaca ese elemento se pone en un nodo y este nodo es el primero y nico en la lista. La situacin cuando ya existen elementos en la lista es la siguiente:

-4-

Estructura de Datos y Listas Encadenadas En este caso se debe cambiar la referencia "Head" de manera que "apunte" al nuevo nodo que contendr al elemento. El siguiente grfico muestra esta situacin

En este punto es importante destacar que se est aprovechando el mecanismo de administracin de memoria que brindan los lenguajes orientados a objetos (comentando en una publicacin anterior), el que indica que los objetos mantienen una referencia que "apunta" a una zona de memoria que es donde efectivamente se encuentra la informacin del objeto. De este modo es posible cambiar el valor de la referencia "Head" de manera que apunte a otra zona de memoria. En programacin no orientada a objetos esto se implementa con un "puntero" que apunta a registros o estructuras del tipo nodo. Otra posibilidad es agregar al final de la lista, para ello (cuando la lista no est vaca) se debe recorrer la misma hasta llegar al final de la misma; eso se determina porque el enlace el ltimo nodo tiene el valor "null". Para eso se utiliza una referencia "Skip" que comienza al principio de la lista y la recorre pasando de un nodo a otro hasta que encuentre el ltimo (aquel cuyo enlace sea igual a null), entonces se procede a "enganchar" el nuevo nodo que contiene al elemento.

Finalmente debera quedar as

Ac ya se observa un problema de performance para cuando la lista tenga un nmero considerable de nodos. Otra situacin en la que se puede querer agregar un elemento es entre dos nodos dados, por ejemplo el nodo "A" y el nodo "B"; en este caso primero hace falta encontrar el "lugar" donde se

-5-

Estructura de Datos y Listas Encadenadas debe realizar la agregacin, esto significa recorrer la lista (con una referencia como por ejemplo Skip) que buscar de alguna manera la posicin adecuada. Se debe tener la precaucin de mantener la referencia Skip "apuntando" al nodo anterior al lugar donde se realizar la agregacin, caso contrario sera imposible. Esto se muestra en el grafico:

El mecanismo de agregacin es un simple cambio de los valores de los enlaces, de manera que quede como indica el grafico:

Observen como el enlace del nodo denominado "A" al cual se hace referencia con Skip apunta al nuevo nodo (el que contiene a Item) y el enlace de este nuevo nodo apunta al nodo "B". La secuencia en que deben realizarse estos pasos se observa mejor en el cdigo que est ms adelante. Obviamente el cdigo debe considerar situaciones como lista vaca o lista con un nico elemento y otras que pueden ocurrir.

Extraccin
La extraccin de elementos se puede realizar solamente si la lista no est vaca en cuyo caso se debe provocar una excepcin dado que es responsabilidad de quin usa la lista controlar que tenga elementos para extraer. Una posibilidad es extraer el primer elemento de la lista, el que se encuentra en la cabeza o Head; el grfico es ms que explicativo de cmo debe realizarse:

Una vez localizado el elemento que se va a extraer, recordemos que el elemento es Item y est dentro de un nodo que en este caso es el primero de la lista, se debe tomar su valor para -6-

Estructura de Datos y Listas Encadenadas devolverlo. El proceso de extraccin se define para extraer elementos no nodos de manera que se debe devolver el elemento no el nodo. El siguiente grfico muestra los cambios que deben realizarse:

De alguna manera el cdigo tiene que haber salvado el valor de Item o una referencia al nodo que se desconecta, caso contrario ser imposible devolver dicho valor. Otra posibilidad es extraer el ltimo elemento de la lista, para ello hace falta recorrer la lista cuidando de llegar hasta el penltimo nodo, si se apunta al ltimo nodo no se puede realizar la desconexin dado que el nodo anterior (el penltimo) es el que mantiene el enlace. El siguiente grfico muestra los cambios que deben realizarse.

La otra alternativa es extraer un elemento que se encuentra en una posicin dado, por ejemplo entre los nodos "A" y "B". La nica posibilidad de hacerlo es con una referencia que apunte al nodo anterior al que contienen el elemento a extraer. El grafico muestra la situacin

Ac se debe cuidar de cancelar el enlace del nodo que contiene a Item, el que apunta al nodo "B" y por supuesto para que la lista quede correctamente formada y no se pierda nada, se debe ajustar el enlace del nodo "A" de modo que apunte al nodo "B". En el cdigo se puede ver la secuencia en que estos pasos se realizan para no cometer errores.

-7-

Estructura de Datos y Listas Encadenadas

Comportamiento de listas encadenadas bsica


Como se indic, la agregacin y extraccin de elementos en una lista se puede realizar de las formas ms variadas y ocurrentes; sin embargo en una primera implementacin se puede considerar la agregacin solamente por la cabeza (head) y por la cola (tail) de la lista. Otras operaciones interesantes son las de buscar un determinado elemento dentro de la lista y por supuesto recorrerla la lista, no se debe olvidar la comprobacin del estado dado que la lista puede estar vaca. No se determina si la lista est llena dado que la implementacin es dinmica y la lista solamente "se llena" cuando no hay memoria disponible, en cuyo caso difcilmente funcione la aplicacin. Con todo esto en mente se puede detallar los miembros pblicos de la implementacin Constructores List List() Constructor por defecto, inicializa la estructura interna del objeto. Propiedades bool IsEmpty Verdadero si la lista est vaca. Mtodos void AddToHead(ELEMENT item) Agrega un objeto del tipo ELEMENT por la cabeza (head) de la lista. void AddToTail(ELEMENT item) Agrega un objeto del tipo ELEMENT por la cola (tail) de la lista. ELEMENT RemoveFromHead() Extrae el elemento que se encuentra en la cabeza (head) de la lista, obviamente la lista debe contener elementos. ELEMENT RemoveFromTail() Extrae el elemento que se encuentra en la cola (tail) de la lista, la que debe contener elementos. bool Contains(ELEMENT item) Busca un elemento en la lista y regresa un valor lgico, verdadero si el elemento se encuentra en la lista. Requiere que los objetos del tipo ELEMENT implementen un mecanismo de comparacin o puedan decir cuando dos objetos de dicho tipo son iguales.

Los mtodos para agregar y extraer algn elemento en particular, por ahora los dejamos de lado dado que su implementacin depende de cmo se localiza el elemento en cuestin. El recorrido de una lista, o sea permitir que desde fuera del objeto del tipo lista se tenga acceso a cada uno de los elementos que contiene es un tema de programacin un poco ms avanzada; con los actuales lenguajes de programacin orientada a objetos se puede implementar mediante indexadores, enumeradores y/o delegados. Veremos alguno de ellos ms adelante.

-8-

Estructura de Datos y Listas Encadenadas

Cdigo fuente de List.cs


using System; namespace DemoLista1 { /// <summary> /// Implementacin bsica de lista enlazada /// </summary> /// <typeparam name="ELEMENT">Tipo de dato de elementos que se introduce en la lista</typeparam> public class List <ELEMENT> { #region Estructura interna /// <summary> /// Mantiene un punto de entrada a la lista /// </summary> private Node<ELEMENT> head; #endregion #region Constructores /// <summary> /// Constructor por defecto /// </summary> public List() { this.head = null; } #endregion #region Propiedades /// <summary> /// Devuelve verdadero cuando la lista est vaca /// </summary> public bool IsEmpty { get { return this.head == null; } } #endregion #region Comportamiento de la lista enlazada /// <summary> /// Agrega un elemento al principio de la lista /// </summary> /// <param name="item">Elemento a agregar</param> public void AddToHead(ELEMENT item) { if (head == null) { head = new Node<ELEMENT>(item, null);

-9-

Estructura de Datos y Listas Encadenadas


} else { Node<ELEMENT> temp = new Node<ELEMENT>(item, head); head = temp; } } /// <summary> /// Agrega un elemento al final de la lista /// </summary> /// <param name="item">Elemento a agregar</param> public void AddToTail(ELEMENT item) { if (head == null) { head = new Node<ELEMENT>(item, null); } else { Node<ELEMENT> temp = head; while (temp.Next != null) { temp = temp.Next; } temp.Next = new Node<ELEMENT>(item, null); } } /// <summary> /// Determina si un elemento determinado se encuentra en la lista /// </summary> /// <param name="item">Elemento a buscar</param> /// <returns>Verdadero si el elemento se encuentra en la lista</returns> public bool Contains(ELEMENT item) { for (Node<ELEMENT> temp = head; temp != null; temp = temp.Next) { if (temp.Item.Equals(item)) { return true; } } return false; } /// <summary> /// Retira el elemento del principio de la lista /// </summary> /// <returns>Elemento retirado</returns> public ELEMENT RemoveFromHead() { if (IsEmpty) { throw new Exception("Lista vaca"); } Node<ELEMENT> temp = head; head = head.Next; // Avanza la posicin de head temp.Next = null; // Asegurarse de anular la referencia

- 10 -

Estructura de Datos y Listas Encadenadas


return temp.Item; // Devolver el elemento no el nodo } /// <summary> /// Retira el elemento al final de la lista /// </summary> /// <returns>Elemento retirado</returns> public ELEMENT RemoveFromTail() { if (IsEmpty) { throw new Exception("Lista vaca"); } Node<ELEMENT> temp = head; if (temp.Next == null) { head = null; } else { Node<ELEMENT> skip = head; while (skip.Next.Next != null) { skip = skip.Next; } temp = skip.Next; skip.Next = null; // Cancelar el enlace al ltimo nodo } return temp.Item; } #endregion #region Mtodos heredados de object /// <summary> /// Representacin del contenido de la lista /// </summary> /// <returns>Cadena con el contenido de la lista</returns> public override string ToString() { string s = ""; for (Node<ELEMENT> temp = head; temp != null; temp = temp.Next) { s += temp.Item.ToString() + "\n"; } return s; } #endregion } }

Cdigo fuente para probar listas encadenadas bsicas


A continuacin se muestra el cdigo fuente para probar la lista encadenada bsica, para hacerlo ms interesante se utilizan objetos del tipo Person (persona) que mnimamente tienen nombre,

- 11 -

Estructura de Datos y Listas Encadenadas apellido, un constructor que permite fijar estos valores y una sobrecarga de ToString para obtener su contenido. Person.cs
using System; namespace DemoLista1 { public class Person { /// <summary> /// Campos de la estructura interna /// </summary> private string firstName; private string lastName; private DateTime birthDate; /// <summary> /// Constructor por defecto /// Inicializa los campos de la estructura interna en valores vacos, en /// el caso de string cadena vacia y para la fecha el valor mnimo. /// </summary> public Person() { // No hace falta utilizar this porque se refiere a los campos de la // estructura interna firstName = string.Empty; lastName = string.Empty; birthDate = DateTime.MinValue; } /// <summary> /// Constructor especializado, facilita los tres valores /// </summary> /// <param name="firstName">Primer nombre</param> /// <param name="lastName">Ultimo nombre (apellido)</param> /// <param name="birthDate">Fecha de nacimiento</param> public Person(string firstName, string lastName, DateTime birthDate) { // Se debe utilzar this para diferenciar entre los campos de la // estructura interna y los parmetros this.firstName = firstName; this.lastName = lastName; this.birthDate = birthDate; } public Person(string firstName, string lastName) : this() { // Se invoca el contructor por defecto para que fije el valor // que no se pasa como parmetro this.firstName = firstName; this.lastName = lastName; } /// <summary> /// Implementacin para mostrar los atributos de un objeto /// </summary>

- 12 -

Estructura de Datos y Listas Encadenadas


/// <returns>Cadena con la representacin de la estructura interna</returns> public override string ToString() { return firstName + " " + lastName; // +" Naci " + birthDate.ToString(); } } }

Program.cs
using System; namespace DemoLista1 { class Program { static void Main(string[] args) { List<Person> lista = new List<Person>(); lista.AddToHead(new Person("Juan", "Perez")); Console.WriteLine("Lista Continene:\n{0}", lista.ToString()); Console.WriteLine("Se agrega a alguien por la cabeza de la lista"); lista.AddToHead(new Person("Carlos", "Rodriguez")); Console.WriteLine("Lista Continene:\n{0}", lista.ToString()); Console.WriteLine("Se agrega a alguien por la cola de la lista"); lista.AddToTail(new Person("Mara", "Martinez")); Console.WriteLine("Lista Continene:\n{0}", lista.ToString()); Console.WriteLine("Se agrega por la cabeza y luego por la cola de la lista"); lista.AddToHead(new Person("Carla", "Andrada")); lista.AddToTail(new Person("Marcos", "Gimenez")); Console.WriteLine("Lista Continene:\n{0}", lista.ToString()); Console.WriteLine("Se extrae alguien de la cabeza de la lista"); Person alguien; alguien = lista.RemoveFromHead(); Console.WriteLine("Se retiro a: {0}", alguien.ToString()); Console.WriteLine("Lista Continene:\n{0}", lista.ToString()); Console.WriteLine("Se extrae alguien de la cabeza de la lista"); alguien = lista.RemoveFromTail(); Console.WriteLine("Se retiro a: {0}", alguien.ToString()); Console.WriteLine("Lista Continene:\n{0}", lista.ToString()); } } }

- 13 -

Estructura de Datos y Listas Encadenadas La salida correspondiente a la prueba es la siguiente:

Cuestiones de performance
Para solucionar el problema de agregar al final de la listas que en la implementacin realizada necesita de una referencia que recorra toda la lista, se puede considerar mantener dentro de la estructura interna de la lista otra referencia que apunte al final de la misma, grficamente sera algo como lo siguiente:

De este modo se cuenta con un acceso directo al ltimo nodo de la lista, permitiendo una agregacin inmediata tanto por la cabeza (Head) o la cola (Tail). - 14 -

Estructura de Datos y Listas Encadenadas Con esta implementacin se incorpora un miembro a la estructura interna de la lista y se corrigen todos los mtodos de manera que mantengan ambas referencias: Head y Tail. Es interesante notar que se puede cambiar la estructura interna, el cdigo de cada mtodo (cuando haga falta) y realizar la misma prueba para mostrar lo que en el paradigma orientado a objetos se indica como Encapsulamiento, la facultad de ocultar estructura interna y cdigo de mtodos al "mundo exterior" solamente respetando los mensajes que implementan el comportamiento.

Cdigo fuente de List.cs mejorado


using System; namespace DemoLista2 { /// <summary> /// Implementacin de lista enlazada con dos puntos de acceso /// </summary> /// <typeparam name="ELEMENT">Tipo de dato de elementos que se introduce en la lista</typeparam> public class List <ELEMENT> { #region Estructura interna /// <summary> /// Mantiene un punto de entrada a la cabeza de lista /// </summary> private Node<ELEMENT> head; /// <summary> /// Mantiene un punto de entrada al ltimo nodo de la lista /// </summary> private Node<ELEMENT> tail; #endregion #region Constructores /// <summary> /// Constructor por defecto /// </summary> public List() { this.head = null; this.tail = null;

- 15 -

Estructura de Datos y Listas Encadenadas


} #endregion #region Propiedades /// <summary> /// Devuelve verdadero cuando la lista est vaca /// </summary> public bool IsEmpty { get { return this.head == null; } } #endregion #region Comportamiento de la lista enlazada /// <summary> /// Agrega un elemento al principio de la lista /// </summary> /// <param name="item">Elemento a agregar</param> public void AddToHead(ELEMENT item) { if (head == null) { head = new Node<ELEMENT>(item, null); tail = head; } else { Node<ELEMENT> temp = new Node<ELEMENT>(item, head); head = temp; } } /// <summary> /// Agrega un elemento al final de la lista /// </summary> /// <param name="item">Elemento a agregar</param> public void AddToTail(ELEMENT item) { if (head == null) { head = new Node<ELEMENT>(item, null); tail = head; } else { tail.Next = new Node<ELEMENT>(item, null); tail = tail.Next; } } /// <summary> /// Determina si un elemento determinado se encuentra en la lista /// </summary> /// <param name="item">Elemento a buscar</param>

- 16 -

Estructura de Datos y Listas Encadenadas


/// <returns>Verdadero si el elemento se encuentra en la lista</returns> public bool Contains(ELEMENT item) { for (Node<ELEMENT> temp = head; temp != null; temp = temp.Next) { if (temp.Item.Equals(item)) { return true; } } return false; } /// <summary> /// Retira el elemento del principio de la lista /// </summary> /// <returns>Elemento retirado</returns> public ELEMENT RemoveFromHead() { if (IsEmpty) { throw new Exception("Lista vaca"); } Node<ELEMENT> temp = head; head = head.Next; // Avanza la posicin de head if (head == null) // Es el nico elemento en la lista? { tail = null; } temp.Next = null; // Asegurarse de anular la referencia return temp.Item; // Devolver el elemento no el nodo } /// <summary> /// Retira el elemento al final de la lista /// </summary> /// <returns>Elemento retirado</returns> public ELEMENT RemoveFromTail() { if (IsEmpty) { throw new Exception("Lista vaca"); } Node<ELEMENT> temp = head; if (temp.Next == null) { head = null; tail = null; } else { Node<ELEMENT> skip = head; while (skip.Next.Next != null) { skip = skip.Next; } tail = skip; // Ajusta el enlace al ltimo nodo

- 17 -

Estructura de Datos y Listas Encadenadas


temp = skip.Next; tail.Next = null; // Cancelar el enlace al ltimo nodo } return temp.Item; } #endregion #region Mtodos heredados de object /// <summary> /// Representacin del contenido de la lista /// </summary> /// <returns>Cadena con el contenido de la lista</returns> public override string ToString() { string s = ""; for (Node<ELEMENT> temp = head; temp != null; temp = temp.Next) { s += temp.Item.ToString() + "\n"; } return s; } #endregion } }

Nota: Como dije, se puede realizar la prueba con el mismo cdigo de la primer implementacin (cuidado con los namespace).

Consideraciones
Se ha solucionado el problema para agregar al final, sin embargo para extraer el ltimo elemento es inevitable tener que recorrer la lista desde el principio. Obviamente existe una solucin para esta situacin y pasa por tener en cada nodo dos enlaces, uno que apunta al siguiente nodo y otro que apunta al nodo anterior; de este modo se puede acceder al ltimo nodo de la lista y "retroceder" gracias al enlace hacia el nodo anterior para "desengancharlo". Por otro lado, todava queda en el tintero las cuestiones de agregar y extraer elementos del medio de la lista, para lo que hace falta un mecanismo de "localizacin" de elementos. Estos puntos forman parte de otra publicacin.

- 18 -

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