Documentos de Académico
Documentos de Profesional
Documentos de Cultura
ED Java PDF
ED Java PDF
1. Antecedentes
Introducción a la Orientación a Objetos
Encapsulación.
Polimorfismo.
Herencia.
En cualquier caso, la clase hija hereda todas las cualidades asociadas con
la clase padre y le añade sus propias características definitorias. Sin el uso de
clasificaciones ordenadas, cada objeto tendría que definir todas las
características que se relacionan con él explícitamente.
Un TDA define lo que cada operación debe hacer, más no como la debe
hacer. En un lenguaje de programación como Java un TDA puede ser
expresado como una interface, que es una simple lista de declaraciones de
métodos.
Ejemplos de tipos de datos abstractos son las Listas, Pilas, Colas, etc., que se
discutirán más adelante.
Estructuras de Datos
Resumen de Java
2. Arreglos
Arreglos lineales
Declaración:
Como se sabe, hay 2 tipos de datos en Java: primitivos (como int y double) y
objetos. En muchos lenguajes de programación (aún en Orientados a Objetos
como C++) los arreglos son tipos primitivos, pero en Java son tratados como
objetos. Por consiguiente, se debe utilizar el operador new para crear un
arreglo:
Para acceder a los elementos de un arreglo se debe utilizar los corchetes, muy
similar a otros lenguajes de programación:
Ejemplo:
// array.java
// demonstrates Java arrays
////////////////////////////////////////////////////////////////
class ArrayApp
{
public static void main(String[] args) {
int[] arr; // reference
arr = new int[100]; // make array
int nElems = 0; // number of items
int j; // loop counter
int searchKey; // key of item to search for
//--------------------------------------------------------------
arr[0] = 77; // insert 10 items
arr[1] = 99;
arr[2] = 44;
arr[3] = 55;
arr[4] = 22;
arr[5] = 88;
arr[6] = 11;
arr[7] = 00;
arr[8] = 66;
arr[9] = 33;
nElems = arr.length; // now 10 items in array
//-------------------------------------------------------------
for (j=0; j<nElems-1; j++) // display items {
System.out.print(arr[j] + " ");
System.out.println("");
}
//--------------------------------------------------------------
searchKey = 66; // find item with key 66
for (j=0; j<nElems; j++) // for each element,
if(arr[j] == searchKey) // found item?
break; // yes, exit before end
if(j == nElems) // at the end?
System.out.println("Can't find " + searchKey); // yes
else
System.out.println("Found " + searchKey); // no
//--------------------------------------------------------------
searchKey = 55; // delete item with key 55
for (j=0; j<nElems; j++) // look for it
if(arr[j] == searchKey)
break;
for (int k=j; k<nElems; k++) // move higher ones down
arr[k] = arr[k+1];
nElems--; // decrement size
//--------------------------------------------------------------
for (j=0; j<nElems; j++) { // display items
System.out.print( arr[j] + " ");
System.out.println("");
}
} // end main()
} // end class ArrayApp
77 99 44 55 22 88 11 0 66 33
Found 66
77 99 44 22 88 11 0 66 33
- Insertar elementos
- Búsqueda de elementos
- Eliminar elementos
- Mostrar los elementos
- Ordenar los elementos
- Modificar algún elemento
Arreglos bidimensionales
double [][] temperatures = new double [2][2]; // Dos filas y dos columnas.
3. Listas ligadas
Definición
Ahora veremos una estructura de datos que resuelve los problemas anteriores,
llamada lista ligada. Las listas ligadas, son probablemente, la segunda
estructura de almacenamiento de propósito general más comúnmente
utilizadas, después de los arreglos.
Algunas listas más complejas son las listas doblemente ligadas o las listas
circulares, por nombrar algunas.
Lista doblemente ligada
Lista circular
Listas desordenadas
Tope de la Lista
Lógicamente, una lista es tan solo un objeto de una clase Lista que se
conforma de un tope (posición de inicio) de lista y un conjunto de métodos
para operarla.
Una lista ordenada, es una extensión de las listas normales con la cualidad
de que todos sus datos se encuentran en orden. Como al igual que las listas se
debe poder insertar datos, hay dos formas de garantizar el orden de los
mismos:
“Nuestro Dato”
La clase Lista
NULL
Tope de la lista
“”
Consideraciones:
null
Tope de la
Nodo que se
lista
eliminará
null
Tope de la
lista
Nodo que se
eliminará
null
Tope de la
lista Nodo que se
eliminará
Mostrar la lista
Funciones adicionales
a) tamaño de la lista
b) lista vacía
c) fin de la lista
d) insertar en una lista ordenada
e) ordenar una lista desordenada
f) buscar un elemento de la lista
4. Pilas
Definición
Aunque los objetos son todos diferentes, todos ilustran el concepto de pila
(stack). Una pila, es una particularización de las listas y se puede definir como
una estructura en la cual los elementos son agregados y eliminados en el tope
de la lista. Es una estructura LIFO (L ast In First Out – el primero que llega es el último
que sale).
Las pilas cuentan solo con 2 operaciones, conocidas como PUSH, insertar
un elemento en el tope de la pila, y POP, leer el elemento del tope de la pila.
Veamos como funcionan estos métodos:
PUSH
Tope
de la
pila
Tope
de la
pila
Tope de la pila
POP
Tope aux
2.- Hacer el tope de la pila igual al siguiente del temporal
Tope
3.- Regresar el valor del nodo temporal antes que desaparezca
Tope
Implementación de pilas
Para trabajar con pilas, utilizaremos la misma base con la que trabajamos
para las listas. Dispondremos de 2 clases: Pila y NodoDePila. Con la primera
crearemos a la pila y las operaciones sobre ella y con la segunda
instanciaremos a cada uno de los nodos de la pila.
Una cola es una estructura de datos similar a una lista con restricciones
especiales. Los elementos son agregados en la parte posterior de la cola y son
eliminados por el frente. Esta estructura es llamada FIFO (F irst In, First Out – el
primero que llega, es el primero en salir). Considere la siguiente figura:
último primero
Construcción de colas
Insertar
Insertar un dato en una cola es muy similar a hacerlo en una pila o una
lista, la diferencia es que tendremos que hacerlo por el final de la cola. A
este proceso se le llama encolar.
último primero
último primero
último primero
Eliminar
1.-
último primero
2.-
último último
3.-
último primero
6. Árboles
Recursión
Alguna vez hemos visto ese conjunto de muñecos de madera de origen ruso
(matrioshkas) en la que uno se encuentra dentro de otro. Dentro del primer
muñeco, se encuentra un muñeco menor, y dentro de ese muñeco, hay otro
muñeco de menor tamaño y así sucesivamente. Un método recursivo es como
los muñecos rusos: se reproducen a sí mismo con versiones más y más
pequeñas.
Pero ahora nos damos cuenta que desconocemos el factorial de 2, así que
procedemos a calcularlo
Sucesión de Fibonacci
Encontrar un nodo hoja en árboles
Recorrer una lista
Etc
Definición
Árboles binarios
Salvo que trabajemos con árboles especiales, como los que veremos más
adelante, las inserciones serán siempre en punteros de nodos hoja o en
punteros libres de nodos rama. Con estas estructuras no es tan fácil
generalizar, ya que existen muchas variedades de árboles.
Recorridos
Esos recorridos dependen en gran medida del tipo y propósito del árbol,
pero hay ciertos recorridos que usaremos frecuentemente. Se trata de
aquellos recorridos que incluyen todo el árbol.
RecorrerArbol(raiz);
Pre-orden:
void PreOrden(NodoDeArbol a) {
if (a == NULL) return;
Procesar(dato); //método que lee el dato
RecorrerArbol(a.izq);
RecorrerArbol(a.centro);
RecorrerArbol(a.der);
}
ABEKFCGLMDHIJNO
In-orden:
void InOrden(NodoDeArbol a) {
if (a == NULL) return;
RecorrerArbol(a.izq);
Procesar(dato); //método que lee el dato
RecorrerArbol(a.centro);
RecorrerArbol(a.der);
}
Post-orden:
void PostOrden(NodoDeArbol a) {
if (a == NULL) return;
RecorrerArbol(a.izq);
RecorrerArbol(a.centro);
RecorrerArbol(a.der);
Procesar(dato); //método que lee el dato
}
KEFBLMGCHINOJDA
Arboles ordenados
Operaciones en ABB.
Buscar un elemento.
Insertar un elemento.
Eliminar un elemento.
Movimientos a través del árbol:
o Izquierda.
o Derecha.
o Raíz.
Información:
o Comprobar si un árbol está vacío.
o Calcular el número de nodos.
o Comprobar si el nodo es hoja.
o Calcular el nivel de un nodo.
o Calcular la altura de un árbol.
Buscar un elemento.
Insertar un elemento.
Padre = NULL
nodo = Raiz
Bucle: mientras actual no sea un árbol vacío o hasta que se encuentre
el elemento.
o Si el valor del nodo raíz es mayor que el elemento que
buscamos, continuaremos la búsqueda en el árbol izquierdo:
Padre=nodo, nodo=nodo->izquierdo.
Padre=nodo, nodo=nodo->derecho.
Eliminar un elemento.
Padre = NULL
Si el árbol está vacío: el elemento no está en el árbol, por lo tanto
salimos sin eliminar ningún elemento.
(*) Si el valor del nodo raíz es igual que el del elemento que buscamos,
estamos ante uno de los siguientes casos:
o El nodo raíz es un nodo hoja:
Si 'Padre' es NULL, el nodo raíz es el único del árbol, por
lo tanto el puntero al árbol debe ser NULL.
Si raíz es la rama derecha de 'Padre', hacemos que esa
rama apunte a NULL.
Si raíz es la rama izquierda de 'Padre', hacemos que esa
rama apunte a NULL.
Eliminamos el nodo, y salimos.
o El nodo no es un nodo hoja:
Buscamos el 'nodo' más a la izquierda del árbol derecho de
raíz o el más a la derecha del árbol izquierdo. Hay que
tener en cuenta que puede que sólo exista uno de esos
árboles. Al mismo tiempo, actualizamos 'Padre' para que
apunte al padre de 'nodo'.
Intercambiamos los elementos de los nodos raíz y 'nodo'.
Borramos el nodo 'nodo'. Esto significa volver a (*), ya que
puede suceder que 'nodo' no sea un nodo hoja.
Si el valor del nodo raíz es mayor que el elemento que buscamos,
continuaremos la búsqueda en el árbol izquierdo.
Si el valor del nodo raíz es menor que el elemento que buscamos,
continuaremos la búsqueda en el árbol derecho.
Para movernos a través del árbol usaremos punteros auxiliares, de modo que
desde cualquier puntero los movimientos posibles serán: moverse al nodo raíz
de la rama izquierda, moverse al nodo raíz de la rama derecha o moverse al
nodo Raíz del árbol.
Información
Tenemos dos opciones para hacer esto, una es llevar siempre la cuenta de
nodos en el árbol al mismo tiempo que se añaden o eliminan elementos. La
otra es, sencillamente, contarlos.
Para contar los nodos podemos recurrir a cualquiera de los tres modos de
recorrer el árbol: inorden, preorden o postorden, como acción sencillamente
incrementamos el contador.
Esto es muy sencillo, basta con comprobar si tanto el árbol izquierdo como el
derecho están vacíos. Si ambos lo están, se trata de un nodo hoja.
2, 4, 5, 8, 9, 12
Bibliografía
[1] Nell Dale, Object-oriented Data Structures using Java, Jones and Bartlett
Publishers, 2002.
[2] Robert Lafore, Data Structures and Algorithms in Java, Sams, 1998.