listas circulares

Anuncio
Universidad Los Ángeles de Chimbote
Curso: Estructuras de datos
LISTAS CIRCULARES
Una lista circular es una lista lineal en la que el último elemento apunta al
primero. Entonces es posible acceder a cualquier elemento de la lista desde
cualquier punto dado. Las operaciones sobre una lista circular resultan más
sencillas ya que se evitan casos especiales. Por ejemplo, el método añadir de la
clase ClistaLinealSE expuesta anteriormente contempla dos casos: insertar al
principio de la lista e insertar a continuación de un elemento. La siguiente figura
muestra cómo se ve una lista circular simplemente enlazada.
ultimo
Cuando recorremos una lista circular, diremos que hemos llegado al final de
la misma cuando nos encontremos de nuevo en el punto de partida, suponiendo,
desde luego, que el punto de partida se guarda de alguna manera en la lista; por
ejemplo con una referencia fija al mismo. Esta referencia puede ser al primer
elemento de la lista, también puede ser al último elemento, en cuyo caso también
es conocida la dirección del primer elemento. Otra posible solución sería poner un
elemento especial identificable en cada lista circular como lugar de partida. Este
elemento especial recibe el nombre de elemento de cabecera de la lista. Esto
presenta, además, la ventaja de que la lista circular no estará nunca vacía.
Como ejemplo, vamos a construir una lista circular con una referencia fija al
último elemento es equivalente a una lista lineal recta con dos referencias, una al
principio y otra al final.
Para construir una lista circular, primero tendremos que definir la clase de
objetos que van a formar parte de la misma. Por ejemplo, cada elemento de la lista
puede definirse como una estructura de datos con dos miembros: una referencia al
elemento siguiente y otra al área de datos . El área de datos puede ser de un tipo
predefinido o de un tipo definido por el usuario. Según esto, el tipo de cada
elemento de la lista puede venir definido de la siguiente forma:
private class CElemento
{
// Atributos
private Object datos;
// referencia a los datos
private CElemento siguiente; // siguiente elemento
// Métodos
private CElemento() {} // constructor
Curso: Estructuras de datos
Docente : Ing. Hèctor Fiestas Bancayàn
Universidad Los Ángeles de Chimbote
Curso: Estructuras de datos
private CElemento(Object d, CElemento s) // constructor
{
datos = d;
siguiente = s;
}
}
Vemos que por tratarse de una lista lineal simplemente enlazada, aunque
sea circular, la estructura de sus elementos no varía con respecto a lo estudiado
anteriormente.
Podemos automatizar el proceso de implementar una lista circular diseñando
una clase CListaCircularSE (Clase Lista Circular Simplemente Enlazada) que
proporcione los atributos y métodos necesarios para crear cada elemento de la
lista, así como para permitir el acceso a los mismos. Esta clase nos permitirá
posteriormente derivar otras clases que sean más específicas, por ejemplo, una
clase para manipular pilas o una clase para manipular colas. Estas estructuras de
datos las estudiaremos un poco más adelante.
La clase CListaCircularSE
La clase CListaCircularSE que vamos a implementar incluirá un atributo
último que valdrá null cuando la lista esté vacía y cuando no, referenciará siempre
a su último elemento; una clase interna, CELemento, que definirá la estructura de
los elementos; y los métodos indicados en la tabla siguiente:
Método
tamaño
Significado
Devuelve el número de elementos de la lista. No tiene
parámetros.
añadirAlPrincipio
Añade un elemento al principio (el primer elemento es el
referenciado por ultimo.siguiente). Tiene un parámetro que
es una referencia de tipo Object al objeto a añadir. No
devuelve ningún valor.
añadirAlFinal
Añade un elemento al final (el último elemento siempre
estará referenciado por ultimo). Tiene un parámetro que es
una referencia de tipo Object al objeto a añadir. No
devuelve ningún valor.
borrar
Borra el primer elemento (el primer elemento es el
referenciado por ultimo.siguiente). No tiene parámetros.
Devuelve una referencia al objeto borrado o null si la lista
está vacía.
obtener
Devuelve el elemento de la posición i o bien null si la lista
está vacía o el índice está fuera de los límites. Tiene un
Curso: Estructuras de datos
Docente : Ing. Hèctor Fiestas Bancayàn
Universidad Los Ángeles de Chimbote
Curso: Estructuras de datos
parámetro correspondiente a la posición i del objeto que se
desea obtener.
A continuación se presenta el código correspondiente a la definición de la clase
CListaCircularSE.
//////////////////////////////////////////////////////////////////
// Lista lineal circular simplemente enlazada
//
public class CListaCircularSE
{
// último: referencia el último elemento.
// último.siguiente referencia al primer elemento de la lista.
private CElemento último = null;
// Elemento de una lista lineal circular simplemente enlazada
private class CElemento
{
// Atributos
private Object datos;
// referencia a los datos
private CElemento siguiente; // siguiente elemento
// Métodos
private CElemento() {} // constructor
private CElemento(Object d, CElemento s) // constructor
{
datos = d;
siguiente = s;
}
}
public CListaCircularSE() {} // constructor
public int tamaño()
{
// Devuelve el número de elementos de la lista
if (último == null) return 0;
CElemento q = último.siguiente;
// primer elemento
int n = 1;
// número de elementos
while (q != último)
{
n++;
q = q.siguiente;
}
return n;
}
public void añadirAlPrincipio(Object obj)
{
Curso: Estructuras de datos
Docente : Ing. Hèctor Fiestas Bancayàn
Universidad Los Ángeles de Chimbote
Curso: Estructuras de datos
// Añade un elemento al principio de la lista.
// Crear el nuevo elemento.
CElemento q = new CElemento(obj, null);
if( último != null ) // existe una lista
{
q.siguiente = último.siguiente;
último.siguiente = q;
}
else
// inserción del primer elemento
{
último = q;
último.siguiente = q;
}
}
public void añadirAlFinal(Object obj)
{
// Añade un elemento al final de la lista.
// Por lo tanto, último referenciará este nuevo elemento.
// Crear el nuevo elemento.
CElemento q = new CElemento(obj, null);
if( último != null ) // existe una lista
{
q.siguiente = último.siguiente;
último = último.siguiente = q;
}
else
// inserción del primer elemento
{
último = q;
último.siguiente = q;
}
}
public Object borrar()
{
// Devuelve una referencia a los datos del primer elemento de
// la lista y borra este elemento.
if( último == null )
{
System.err.println( "Lista vacía\n" );
return null;
}
CElemento q = último.siguiente;
Object obj = q.datos;
if( q == último )
último = null;
else
último.siguiente = q.siguiente;
Curso: Estructuras de datos
Docente : Ing. Hèctor Fiestas Bancayàn
Universidad Los Ángeles de Chimbote
Curso: Estructuras de datos
return obj;
// El elemento referenciado por q es enviado a la basura, al
// quedar desreferenciado cuando finaliza este método por ser
// q una variable local.
}
public Object obtener(int i)
{
// Obtener el elemento de la posición i
int númeroDeElementos = tamaño();
if (i >= númeroDeElementos || i < 0)
return null;
CElemento q = último.siguiente; // primer elemento
// Posicionarse en el elemento i
for (int n = 0; n < i; n++)
q = q.siguiente;
// Retornar los datos
return q.datos;
}
}
//////////////////////////////////////////////////////////////////
Una vez que hemos escrito la clase CListaCircularSE, vamos a realizar una
aplicación que utilizàndola cree una lista circular y ponga a prueba las distintas
operaciones que sobre ella pueden realizarse. Los elementos de esta lista serán
objetos de la clase CDatos utilizada en ejemplos anteriores. El código de esta
aplicación puede ser el siguiente:
//////////////////////////////////////////////////////////////////
// Crear una lista lineal circular simplemente enlazada
//
public class Test
{
public static void mostrarLista(CListaCircularSE lcse)
{
// Mostrar todos los elementos de la lista
int i = 0, tam = lcse.tamaño();
CDatos obj;
while (i < tam)
{
obj = (CDatos)lcse.obtener(i);
System.out.println(i + ".- " + obj.obtenerNombre() + " " +
obj.obtenerNota());
i++;
}
if (tam == 0) System.out.println("lista vacía");
Curso: Estructuras de datos
Docente : Ing. Hèctor Fiestas Bancayàn
Universidad Los Ángeles de Chimbote
Curso: Estructuras de datos
}
public static void main(String[] args)
{
// Crear una lista circular vacía
CListaCircularSE lcse = new CListaCircularSE();
// Leer datos y añadirlos a la lista
String nombre;
double nota;
int i = 0;
System.out.println("Introducir datos. Finalizar con Ctrl+Z.");
System.out.print("nombre: ");
while ((nombre = Leer.dato()) != null)
{
System.out.print("nota: ");
nota = Leer.datoDouble();
lcse.añadirAlFinal(new CDatos(nombre, nota));
System.out.print("nombre: ");
}
// Añadir un objeto al principio
lcse.añadirAlPrincipio(new CDatos("abcd", 10));
System.out.println("\n");
// Mostrar la lista
System.out.println("Lista:");
mostrarLista(lcse);
// Borrar el elemento primero
CDatos obj = (CDatos)lcse.borrar();
// Mostrar la lista
System.out.println("Lista:");
mostrarLista(lcse);
}
}
**.**
Curso: Estructuras de datos
Docente : Ing. Hèctor Fiestas Bancayàn
Descargar