You are on page 1of 16

Ordenar Listas en Java

julio 10, 2007Francisco Javier Martnez PezSin comentarios

Tutoriales 62631 visitas

Ordenar Listas en Java

En este tutorial pretendo mostrar una forma sencilla de ordenar listas en


java usando dos mtodos estticos de la clase java.util.Collections (si el
lector an no los sabe) e implementando dos interfaces Comparable y
Comparator.
Cuando nosotros creamos una clase de algn tipo, podemos especificar el
orden natural de los objetos de esa clase cuando se encuentran en una
lista, simplemente implementando el interfaz Comparable que declara el
mtodo:
int compareTo(Object o);
ste mtodo compara ste objeto con el objeto recibido como parmetro.
ste mtodo ha de devolver un valor negativo si ste objeto es menor que
el recibido, 0 si son iguales o un valor positivo si es mayor, segn el rden
natural de los objetos.
Vamos a mostrar un ejemplo. Voy a crear la clase Persona con los siguientes
atributos:

Apellidos

Nombre

DNI

Fecha de Nacimiento.

He decidido que para m, la forma natural de ordenar los objetos de la clase


Persona viene definido:

Primeramente por el orden alfabtico de sus apellidos

Despes por el orden alfabtico de su nombre.

Y finalmente por su DNI.


Definimos la clase Persona de esta manera:

public class Persona implements Comparable {


private String nombre;
private String apellidos;
private String dni;
private Date fechaNacimiento;
public String toString() {
return this.apellidos + + this.nombre + + this.dni +
+ DateFormat.getDateInstance(DateFormat.DEFAULT,
Locale.getDefault()).format(this.fechaNacimiento);
}
public Persona(String nombre, String apellidos, String dni, Date
fechaNacimiento) {
this.nombre = nombre;
this.apellidos = apellidos;
this.dni = dni;
this.fechaNacimiento = fechaNacimiento;
}
public String getApellidos() {
return apellidos;
}
public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}

public String getDni() {


return dni;
}
public void setDni(String dni) {
this.dni = dni;
}

Aqu esta un ejemplo de listas en Java utilizando ArrayList:


Lo que hace este programa, es que pide el nombre del alumno y tres calificaciones
para luego calcular su promedio. Se puede agregar cualquier cantidad de elementos a
la lista.

1
2
3
4
5
6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

public class NodoLista4{


String nom;
int calif1;
int calif2;
int calif3;
}
import java.util.*;
public class ListaAlumnos{
static double prom;
public static void main( String args[] ){
Scanner leer = new Scanner(System.in);
NodoLista4 nodo = new NodoLista4();
int op;
ArrayList lista = new ArrayList();
do{

System.out.println( "Ingrese el
nodo.nom = leer.next();
System.out.println( "Ingrese la
nodo.calif1 = leer.nextInt();
System.out.println( "Ingrese la
nodo.calif2 = leer.nextInt();
System.out.println( "Ingrese la
nodo.calif3 = leer.nextInt();

nombre del alumno:" );


primera calificacin:" );
segunda calificacin:" );
tercera calificacin:" );

lista.add("Nombre del alumno:\n"+nodo.nom);


lista.add("Calificacin 1:\n"+nodo.calif1);
lista.add("Calificacin 2:\n"+nodo.calif2);
lista.add("Calificacin 3\n"+nodo.calif3);
promedio(nodo.calif1, nodo.calif2, nodo.calif3);

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 }
45
46
47
48

lista.add("Su promedio es:\n"+prom);


System.out.println( "Desea ingresar otro alumno?" );
System.out.println( "1.-Si\t 2.-No" );
op = leer.nextInt();
}

while(op != 2);
List lista2 = new ArrayList(lista);
Iterator it = lista2.iterator();
while (it.hasNext()){
System.out.println(it.next()+"");
}

private static double promedio(int calif1, int calif2, int calif3){


int suma = calif1 + calif2 + calif3;
prom = suma/3;
return prom;
}

Listas Simplemente Ligadas


Las listas simplemente ligadas son una estructura de datos que nos permite almacenar cualquier
cantidad de datos. La ventaja principal es que la memoria que ocupa es solamente la necesaria a
diferencia de un arreglo que puede desperdiciar memoria que no est en uso (como la memoria que
se desperdicia con los arreglos: generalmente declaras un arreglo del tamao mximo que se podra
llegar a usar aunque muchas veces no se llena).
La lista simplemente ligada puede ser usada para crear estructuras de datos ms complejos.
Consiste en una secuencia de nodos, donde cada nodo contiene informacin y un apuntador al nodo
que sigue. El ltimo nodo apunta a un valor nulo (NULL) lo cual indica que es el final de la lista. De
esta manera se puede recorrer la lista de forma secuencial siempre y cuando tengas un apuntadoral
primer elemento de la lista, como se ve la siguiente imagen (tomada del blog de xrom):

O, si quieres, puedes conceptualizarlo como un tren de vagones donde el tienes un apuntador a la


locomotora y el apuntador al siguiente que hay en cada nodo es el mecanismo con el que se
engancha al vagn que le sigue (Imagen cortesa de Medieducativos):

En este post me voy a enfocar en 3 cosas: agregar un nuevo nodo a la lista (al final), mostrar todos
los nodos (recorrerlo) y eliminar un nodo de la lista. Antes de entrar a estos temas, hay que ver
como se declara la estructura y la forma en que se usa. En este ejemplo, estoy haciendo una lista
que guarda algunos datos de videojuegos. Aqu est la declaracin de la estructura y una variable
global que apunta al primer nodo de la lista:

La funcin principal del programa (main) no tiene mayor ciencia. Bsicamente solo muestra un
men y pide una opcin. En base a la opcin deseada manda llamar funciones para dar de alta,
consultar todos o eliminar alguno. Una nota antes de seguir: este programa lo hice usando el
compilador Dev-C++ varsin 4.9.9.2. Este es el cdigo (haz clic sobre la imagen para verlo ms
grande):

Voy a comenzar hablando de la funcin que da de alta un nodo al final de la lista. Primero declaro
dos apuntadores a struct nodo: Temp y Temp2. Uso la funcin malloc para apartar RAM para
almacenar la estructura de forma dinmica. Si necesitas saber ms sobre el malloc, al final de este
post hay ligas a pginas que son referencias para que despejes dudas sobre su sintaxis y funcin.
Pero a grandes rasgos, el malloc sirve para asignarle memoria y devolver un apuntador hacia el
espacio reservado. Una vez apartada la memoria, lleno el nuevo nodo con los datos (que son los
parmetros nom, plat y pre) y al campo Sig le asigno el valor de NULL porque va a ser el ltimo de
la lista. Al final debo reorganizar los apuntadores: el apuntador Sig del elemento anterior debe
apuntar a este nuevo nodo. El cdigo que lo realiza es el siguiente:

Una vez resuelto el problema de dar de alta nodos, voy a explicar la forma en que se puede recorrer
la lista y mostrar los elementos. Esto lo hice en la funcin llamada MuestraTodo. Declaro un
apuntador llamado Temp (para no perder la costumbre, jeje) con el que voy a recorrer la lista. Uso
la variable i para mostrar el nmero de nodo en el que voy. Al principio igualo Temp a Inicio
para comenzar el recorrido. Y mientras no llego al final (o sea, Temp es diferente de NULL), muestro
lo que contiene el nodo. Fjate como se accesa un elemento por medio de un apuntador ya que
difiere de la forma en que se hace cuando no usas apuntador. En lugar del punto (.), se usa una
especie de flecha compuesta por el guin y el signo mayor que (->). Aqu est el cdigo:

Ahora lo nico que falta es mostrar la funcin que elimina un nodo de la lista. Esto es
relativamente sencillo y creo que el cdigo se explica por si solo (le puse un montn de
comentarios). Bsicamente es igual que la funcin MuestraTodo solo que esta vez, en lugar de
mostrar el elemento, veo si es igual al que busco. En caso que sea igual, veo si es el primero de la
lista. Si es el primero, solo cambio el valor de Inicio para que apunte al siguiente, y en caso
contrario, modifico el apuntador Sig del elemento anterior (convenientemente apuntado

porAnterior) para que apunte al que sigue. Una vez arreglado los apuntadores, libero la memoria
usando la instruccin free. Al final viene ms ayuda sobre free, pero bsicamente libera la
memoria que es apuntada por un apuntador (valga la redundancia). Al final devuelve un 1 si lo
encontr y lo pudo borrar y un 0 si no lo encuentra. Este es el cdigo de la funcin Eliminalo:

Estas son ligas donde puedes encontrar ms informacin sobre malloc y free (y algunas otras
funciones que te pueden resultar muy tiles). Hasta la prxima!

malloc C con clase o Wikipedia.

free C con clase.

Otros recursos sobre listas simplemente ligadas: todo tipo de listas en Wikipedia y
esteexcelente recurso sobre listas del Cinvestav (ojo: all hay ligas para ver agregar y
eliminar nodos).

Listas ligadas

En las secciones anteriores se contemplaron diferentes estructuras estticas en


dnde la manipulacin de datos es a travs de posiciones localizadas
secuencialmente. Para de clarar estas estructuras se deba definir un tamao

determinado el cual no poda modificarse posteriormente. Esto puede ser un


problema en el caso de que:
no sepamos de antemano el tamao requerido para
nuestra aplicacin
hay una gran cantidad de operaciones y manipulaciones de
los datos dentro de las estructuras
En estos casos es generalmente m&a acute;s conveniente utilizar estructuras
dinmicas, es decir, las cuales pueden aumentar o disminuir de tamao de
acuerdo a los requerimientos especficos del procedimiento. As se resuelve el
problema de no saber el tama&ntild e;o exacto desde un principio y las
manipulaciones de datos se pueden hacer de una manera mas rpida y eficiente.
Una lista ligada es entonces un grupo de datos organizados secuencialmente, pero
a diferencia de los arreglos, la organizacin no esta dada implcitamente por su
posicin en el arreglo. En una lista ligada cada elemento es un nodo que contiene
el dato y adems una liga al siguiente dato. Estas ligas son simplemente variables
que contienen la(s) direccin(es) de los datos contiguos o relacionados.
Para manejar una lista es necesario contar con un apuntador al primer elemento
de la lista "head" .
Las ventajas de las listas ligadas son que:
Permiten que sus tamaos cambien durante la ejecucin
del programa
Proveen una major flexibilidad en el manejo de los datos.
Este principio de listas ligadas se puede aplicar a cualquiera de los conceptos de
estructura de datos vistos anteriormente: arreglos, colas y pilas . Es decir, las
operaciones de altas, bajas y cambios, as como bsquedas y ordenamientos se
tendrn que adaptar en la cuestin del manejo de localidades nicamente.

Listas ligadas sencillas


Una lista ligada sencilla es un grupo de datos en dnde cada dato contiene
adems un apuntador hacia el siguiente dato en la lista, es decir, una liga hacia el
siguiente dato.

Los siguientes algoritmos fueron tomados de "Estructuras de Datos", Cair Guardati, 2a. Ed., McGraw Hill, 2002.

Algoritmo 5.1
CREAINICIO(P)
{Este algoritmo crea una lista, agregando cada nuevo nodo al inicio de la
misma}
{ P y Q son variables de tipo puntero. P apuntar al inicio de la lista}
1.
2.
3.
4.

CREA (P) {Crea el primer nodo de la lista}


Leer P->INFORMACIN
Hacer P->LIGA=NIL
Repetir
CREA (Q)
Leer Q->INFORMACIN
Hacer Q->LIGA= P y P = Q

5.

Hasta (que ya no haya informacin)

Algoritmo 5.2
CREAFINAL(P)
{Este algoritmo crea una lista, agregando cada nuevo nodo al final de la
misma}
{P y Q son variables de tipo puntero. P apuntar al inicio de la lista}
1.
2.
3.
4.

5.

CREA (P) {Crea el primer nodo de la lista}


Leer P->INFORMACIN
Hacer P->LIGA=NIL y T=P
Repetir
CREA (Q)
Leer Q->INFORMACIN
Hacer Q->LIGA=NIL, T->LIGA=Q y T=Q
Hasta (que ya no haya informacin)

Para poder dar de alta un dato en una lista ligada sencilla es necesario recorrer la
lista nodo por nodo hasta encontrar la posicin adecuada. Se crea un nuevo nodo,
se inserta el dato y se actualizan las ligas del nodo nuevo y del anterior para
intercalar el nuevo nodo en la lista.

Algoritmo 5.3
RECORREITERATIVO(P)
{Este algoritmo recorre una lista cuyo primer nodo est apuntado por P}
{Q es una variable de tipo puntero}
1.
2.
3.

Hacer Q = P
Repetir mientras Q =! NIL
Escribir Q->INFORMACUN
Hacer Q=Q->LIGA {Apunta al siguiente nodo de la lista}
{Fin del ciclo del paso 2}

Algoritmo 5.4
RECORRECURSIVO(P)
{Este algoritmo recorre una lista recursivamente.
nodo a visitar}
1.

la lista}
2.

P es el apuntador al

Si P =! NIL entonces
Escribir P->INFORMACIN
Llamar a RECORRECURSIVO con P->LIGA
{Llamada recursiva con el apuntador al siguiente nodo de
{Fin del condicional del paso 1}

Algoritmo 5.6
INSERTAFINAL(P)
{Este algoritmo inserta un nodo al final de la lista. P es el apuntador
al primer nodo
de la lista, y DATO es la informacin que se almacenar en el nuevo nodo}
{Q y T son variables de tipo puntero}
1.
2.
3.
4.
5.

Hacer T= P
Repetir mientras T ->Liga =! NIL
{Recorre la lista hasta llegar al ltimo elemento}
Hacer T=T->LIGA
{Fin del ciclo del paso 2}
CREA (Q)
Hacer Q->INFORMACIN =DATO, Q->LIGA =NIL y T ->LIGA =Q

Algoritmo 5.7
INSERTANTES ( P, DATO, REF )
{Este algoritmo inserta un nodo dado como referencia, REF. P es el
apuntador al
primer nodo de la lista, y DATO es la informacin que se almacenar en el
nuevo nodo}
{Q, X y T son variables de tipo puntero, BAND es una variable de tipo
booleano}
1.
2.
VERDADERO)

Hacer Q= P y BAND= VERDADERO


Repetir mientras (Q->INFORMACIN =! REF) y (BAND =
2.1

3.
4.

5.

Si Q -> LIGA =! NIL


Entonces
Hacer T= Q y Q= Q-> LIGA
Si no
Hacer BAND = FALSO
2.2
{Fin del condicional del paso 2.1}
{Fin del ciclo del paso 2}
Si BAND = VERDADERO entonces
CREA(X)
Hacer X->INFORMACIN = DATO
4.1
Si P = Q {Es el primer nodo}
Entonces
Hacer X ->LIGA = P y P = X
Si no
Hacer T ->LIGA =X y X ->LIGA = Q
4.2
{Fin del condicional del paso 4.1}
{Fin del condicional del paso 4}

Algoritmo 5.9
ELIMINAPRIMERO(P)
{Este algoritmo borra el primer elemento de una lista.
al primer nodo de la lista}
{Q es una variable de tipo puntero}

nodo}

P es el apuntador

1.
2.

Hacer Q = P
Si Q -> LIGA =! NIL {Verifica si la lista tiene slo un

3.
4.

Entonces
Hacer P= Q-> LIGA {Redefine el puntero al inicio}
Si no
Hacer P = NIL
{Fin del condicional del paso2}
QUITA(Q)

Algoritmo 5.10
ELIMINALTIMO(P)
{Este algoritmo borra el ltimo elemento de una lista.
al primer nodo de la lista}
{Q y T son variables de tipo puntero}
1.
elemento}

2.

P es el apuntador

Si P -> LIGA = NIL {Verifica si la lista tiene slo un


Entonces
QUITA(P)
Hacer P = NIL
Si no
Hacer Q = P
1.1
Repetir mientras ( Q->LIGA =! NIL)
Hacer T=Q y Q = Q -> LIGA
1.2
{Fin del ciclo del paso 1.1}
Hacer T -> LIGA = NIL
QUITA(Q)
{Fin del condicional del paso 1}

Algoritmo 5.11
ELIMINAX( P, X )
{Este algoritmo elimina un nodo con informacin X de una lista. P es el
apuntador al primer nodo de la lista}
{Q y T son variables de tipo puntero. BAND es una variable de tipo
booleano}
1.
2.
VERDADERO)

Hacer Q = P y BAND= VERDADERO


Repetir mientras (Q->INFORMACIN =! X) y
2.1

3.
4.

el primero}

5.

(BAND =

Si Q ->LIGA =! NIL
Entonces
Hacer T = Q y Q = Q -> LIGA
Si no
Hacer BAND = FALSO
2.2
{Fin del condicional del paso 2.1}
{Fin del ciclo del paso 2}
Si BAND = FALSO
Entonces
Escribir El elemento no fue encontrado
Si no
4.1
SI P = Q {Verifica si el elemento a eliminar es
Entonces
Hacer P = Q->LIGA
Si no
Hacer T -> LIGA=Q-> LIGA
4.2
{Fin del condicional del paso 4.1}
QUITA(Q)
{Fin del condicional del paso 4}

Algoritmo 5.15
BUSCARRECURSIVO(P,X)
{Este algoritmo busca recursivamente al elemento con informacin X en una
lista que se encuentra desordenada. P es el apuntador del nodo a
visitar}
1.

Si ( P =! NIL)
Entonces
1.1
Si ( P ->INFORMACIN = X )
Entonces
Escribir El elemento se encuentra en la

lista

Si no
1.2

lista

2.

Llamar a BUSCARRECURSIVO con P -> LIGA y X


{Fin del condicional del paso 1.1}
Si no
Escribir El elemento no se encuentra en la

{Fin del condicional del paso 1}

Listas ligadas circulares


Una lista ligada circular es una lista en la cual el ltimo nodo es ligado al primer
elemento de la lista. La ventaja de este tipo de estructura es que siempre se puede
llegar a cualquier nodo siguiendo las ligas. La desventaja e s que si no se tiene
cuidado una bsqueda puede resultar en un ciclo infinito. Esto se puede evitar al
determinar a un nodo como nodo-cabeza o nodo inicial.

Listas ligadas dobles


Hasta ahora se han manejado listas que se recorren en una sla direccin. En
alguna aplicaciones es prctico o hasta indispensable poder recorrer una lista en
ambas direcciones. Para estos casos se tienen las listas doblemente ligadas. Esta
propiedad implica que que cada nodo debe tener dos apuntadores, uno al nodo
predecesor y otro al nodo sucesor.

Las operaciones que se pueden


fundamentalmente las siguientes:
12345-

realizar

con

listas

incluyen

Insertar un elemento en una lista


Buscar un elemento en una lista
Borrar un elemento de una lista
Recorrer los elementos de una lista
Borrar todos los elementos de una lista

*Buscar en una lista un elemento con un valor x


Supongamos que queremos buscar un elemento en una lista cuyo primer
elemento esta apuntado por p. la bsqueda es secuencial y termina
cuando se encuentra el elemento, o bien cuando se llega al final de la
lista.
q=p;
//q apunta al primer elemento de la
lista
cout<<Dato a buscar: ; leerDato(x);
while(q!=0&&q->dato!=x)
q=q->siguiente;
//q apunta al siguiente elemento
Se observa que el orden de las expresiones que forman la condicin del
bucle while. Sabemos que en una operacin &&(AND), cuando una de
las expresiones es falsa la condicin ya es falsa, por lo que el resto de
las expresiones no necesitan ser evaluadas. Cuando q valga cero, la
expresin->dato no ser evaluado, de lo contrario se producir un error.
Finalmente, la variable q quedara apuntando al elemento buscado, o
valdr cero si ese elemento no se encuentra.
*Recorrer una lista
Se quiere realizar una operacin con todos los elementos de una lista,
cuyo primer elemento esta apuntado por p. Ejemplo, escribir el valor de
cada elemento de la lista. Las operaciones son las siguientes:
q=p;
// Salvar el puntero al primer elemento de la lista
while(q!=0)
{
cout<<q->dato<< ;
q=q->siguiente;

}
*Borrar todos los elementos de una lista
Borrar todos los elementos equivale a liberar la memoria asignada a cada
uno de los elementos de la misma. Se quiere borrar una lista, cuyo
primer elemento esta apuntado por p. Sus operaciones son las
siguientes:
while(p!=0)
{
q=p;
p=p->siguiente;
delete q;
}
Antes de borrar el elemento apuntado por q, se hace que p apunte al
siguiente elemento, por que si no se perdera el resto de la lista.

You might also like